home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / mods / makers / octamedv4_dev.lha / ProPlayer / proplayer.a < prev    next >
Encoding:
Text File  |  1993-06-15  |  104.0 KB  |  3,087 lines

  1. ;============================================================================
  2. ;   proplayer.a      © Fully Copyrighted
  3. ;   ~~~~~~~~~~~
  4. ; $VER: proplayer 5.004 (09.06.1993)
  5. ;
  6. ; The music player routine for MMD0/MMD1/MMD2 MED/OctaMED
  7. ; four-channel modules.
  8. ;
  9. ; Written by Teijo Kinnunen.
  10. ; If you find bugs in this routine, please notify:
  11. ;   Teijo Kinnunen
  12. ;   Oksantie 19
  13. ;   FIN-86300  OULAINEN
  14. ;   FINLAND
  15. ;
  16. ; THIS CODE MAY BE FREELY USED AND DISTRIBUTED AS PUBLIC DOMAIN ONLY!
  17. ; IF USING FOR ANY PROFITABLE PURPOSE,(COMMERCIAL etc) SEE ReadMe
  18. ;============================================================================
  19.  
  20. ;****** Feature control ******
  21. ;
  22. MIDI        EQU 0   ;1 = include MIDI code
  23. AUDDEV      EQU 1   ;1 = allocate channels using audio.device
  24. SYNTH       EQU 1   ;1 = include synth-sound handler
  25. CHECK       EQU 1   ;1 = do range checkings (track, sample in mem etc.)
  26. RELVOL      EQU 1   ;1 = include relative volume handling code
  27. IFFMOCT     EQU 1   ;1 = play IFF multi-octave samples/ExtSamples correctly
  28. HOLD        EQU 1   ;1 = handle hold/decay
  29. PLAYMMD0    EQU 1   ;1 = play old MMD0 modules
  30. ;
  31. ; The less features you include, the faster and shorter the play-routine
  32. ; will be.
  33.  
  34. ;****** Timing control ******
  35. ;
  36. VBLANK  EQU 0   ;1 = use VBlank interrupt (when absolutely necessary)
  37. CIAB    EQU 1   ;1 = use CIA timers (default)
  38. ;
  39. ; Please use CIAB whenever possible to avoid problems with variable
  40. ; VBlank speeds and to allow the use of command F01 - FF0 (set tempo)
  41. ; If both are set to 0, the timing is left for you (never set both to 1!!),
  42. ; then you just call _IntHandler for each timing pulse.
  43.  
  44. ;============================================================================
  45.  
  46. ;If you are making a demo/game with only a single tune you'd like to
  47. ;incorporate in the code (like "easyplayer.a" of MED V3), set the following
  48. ;flag to 1. This requires an assembler with INCBIN (or equivalent) directive.
  49. ;You have to type the module name into the INCBIN statement (located near the
  50. ;end of this file, on line 2052).
  51.  
  52. EASY    EQU 0
  53.  
  54. ;Call _startmusic to play the music, and _endmusic to stop it (before
  55. ;exiting). Note: don't call _startmusic twice!! This would cause the module
  56. ;to be relocated twice (= Guru). If you need to stop and continue playing,
  57. ;don't use the EASY routines, use PlayModule/StopPlayer... instead.
  58.  
  59. ;============================================================================
  60.  
  61. ; The MMD structure offsets
  62. mmd_id      EQU 0
  63. mmd_modlen  EQU 4
  64. mmd_songinfo    EQU 8
  65. ; these two for MMD2s only!
  66. mmd_psecnum EQU 12
  67. mmd_pseq    EQU 14
  68. ;
  69. mmd_blockarr    EQU 16
  70. mmd_smplarr EQU 24
  71. mmd_expdata EQU 32
  72. mmd_pstate  EQU 40 ; <0 = play song, 0 = don't play, >0 = play block
  73. mmd_pblock  EQU 42
  74. mmd_pline   EQU 44
  75. mmd_pseqnum EQU 46
  76. mmd_counter EQU 50
  77. mmd_songsleft   EQU 51
  78.  
  79. ; The Song structure
  80. ; Instrument data here (504 bytes = 63 * 8)
  81. msng_numblocks  EQU 504
  82. msng_songlen    EQU 506
  83. msng_playseq    EQU 508
  84. msng_deftempo   EQU 764
  85. msng_playtransp EQU 766
  86. msng_flags  EQU 767
  87. msng_flags2 EQU 768
  88. msng_tempo2 EQU 769
  89. ; msng_trkvol applies to MMD0/MMD1 only.
  90. msng_trkvol EQU 770
  91. msng_mastervol  EQU 786
  92. msng_numsamples EQU 787
  93. ; Fields below apply to MMD2 modules only.
  94. msng_pseqs  EQU 508
  95. msng_sections   EQU 512
  96. msng_trkvoltbl  EQU 516
  97. msng_numtracks  EQU 520
  98. msng_numpseqs   EQU 522
  99.  
  100. ; Instrument data
  101. inst_repeat EQU 0
  102. inst_replen EQU 2
  103. inst_midich EQU 4
  104. inst_midipreset EQU 5
  105. inst_svol   EQU 6
  106. inst_strans EQU 7
  107.  
  108. ; Audio hardware offsets
  109. ac_ptr  EQU $00
  110. ac_len  EQU $04
  111. ac_per  EQU $06
  112. ac_vol  EQU $08
  113.  
  114. ; Trackdata sizes
  115. T03SZ   EQU 98
  116. T415SZ  EQU 20
  117.  
  118. ; Maximum number of tracks allowed. If you don't need this much tracks,
  119. ; you can decrease the number to save some space. (Be sure that the
  120. ; song really has no more than MAX_NUMTRACKS tracks. Minimum allowed
  121. ; value = 4.)
  122. MAX_NUMTRACKS   EQU 64
  123.  
  124. ; This value is used for MMD0/1 conversion. If MAX_NUMTRACKS <= 16,
  125. ; this should be the same. If MAX_NUMTRACKS > 16, this should be 16.
  126. MAX_MMD1_TRACKS EQU 16
  127.  
  128.         SECTION "text",CODE
  129.  
  130.     IFNE    EASY
  131.  
  132.         XDEF    _startmusic,_endmusic
  133.  
  134. _startmusic lea easymod,a2
  135.         bsr.s   _RelocModule
  136.         bsr.w   _InitPlayer
  137.         lea easymod,a0
  138.         bra.w   _PlayModule
  139.  
  140. _endmusic   bra.w   _RemPlayer
  141. ; ***** The relocation routine *****
  142. reloci      move.l  24(a2),d0
  143.         beq.s   xloci
  144.         movea.l d0,a0
  145.         moveq   #0,d0
  146.         move.b  msng_numsamples(a1),d0  ;number of samples
  147.         subq.b  #1,d0
  148. relocs:     bsr.s   relocentr
  149.         move.l  -4(a0),d3   ;sample ptr
  150.         beq.s   nosyn
  151.         move.l  d3,a3
  152.         tst.w   4(a3)
  153.         bpl.s   nosyn       ;type >= 0
  154.         move.w  20(a3),d2   ;number of waveforms
  155.         lea 278(a3),a3  ;ptr to wf ptrs
  156.         subq.w  #1,d2
  157. relsyn      add.l   d3,(a3)+
  158.         dbf d2,relsyn
  159. nosyn       dbf     d0,relocs
  160. xloci       rts
  161. norel       addq.l  #4,a0
  162.         rts
  163. relocentr   tst.l   (a0)
  164.         beq.s   norel
  165.         add.l   d1,(a0)+
  166.         rts
  167. _RelocModule    movem.l a2-a3/d2-d3,-(sp)
  168.         move.l  a2,d1       ;d1 = ptr to start of module
  169.         bsr.s   relocp
  170.         movea.l 8(a2),a1
  171.         bsr.s   reloci
  172. rel_lp      bsr.s   relocb
  173.         cmp.b   #'2',3(a2)  ;MMD2?
  174.         bne.s   norelmmd2
  175.         bsr.w   relocmmd2sng
  176. norelmmd2   move.l  32(a2),d0   ;extension struct
  177.         beq.s   rel_ex
  178.         move.l  d0,a0
  179.         bsr.s   relocentr   ;ptr to next module
  180.         bsr.s   relocentr   ;InstrExt...
  181.         addq.l  #4,a0       ;skip sizes of InstrExt
  182.         bsr.s   relocentr   ;annotxt
  183.         addq.l  #4,a0       ;annolen
  184.         bsr.s   relocentr   ;InstrInfo
  185.         addq.l  #8,a0
  186.         bsr.s   relocentr   ;rgbtable (not useful for most people)
  187.         addq.l  #4,a0       ;skip channelsplit
  188.         bsr.s   relocentr   ;NotationInfo
  189.         bsr.s   relocentr   ;songname
  190.         addq.l  #4,a0       ;skip song name length
  191.         bsr.s   relocentr   ;MIDI dumps
  192.         bsr.s   relocmdd
  193.         move.l  d0,a0
  194.         move.l  (a0),d0
  195.         beq.s   rel_ex
  196.         move.l  d0,a2
  197.         bsr.s   relocp
  198.         movea.l 8(a2),a1
  199.         bra.s   rel_lp
  200. rel_ex      movem.l (sp)+,d2-d3/a2-a3
  201.         rts
  202. relocp      lea 8(a2),a0
  203.         bsr.s   relocentr
  204.         addq.l  #4,a0
  205.         bsr.s   relocentr
  206.         addq.l  #4,a0
  207.         bsr.s   relocentr
  208.         addq.l  #4,a0
  209.         bra.s   relocentr
  210. relocb      move.l  16(a2),d0
  211.         beq.s   xlocb
  212.         movea.l d0,a0
  213.         move.w  msng_numblocks(a1),d0
  214.         subq.b  #1,d0
  215. rebl        bsr.s   relocentr
  216.         dbf     d0,rebl
  217.         cmp.b   #'T',3(a2)
  218.         beq.s   xlocb
  219.         cmp.b   #'1',3(a2)  ;test MMD type
  220.         bge.s   relocbi
  221. xlocb       rts
  222. relocmdd    tst.l   -(a0)
  223.         beq.s   xlocmdd
  224.         movea.l (a0),a0
  225.         move.w  (a0),d0     ;# of msg dumps
  226.         addq.l  #8,a0
  227. mddloop     beq.s   xlocmdd
  228.         bsr relocentr
  229.         bsr.s   relocdmp
  230.         subq.w  #1,d0
  231.         bra.s   mddloop
  232. xlocmdd     rts
  233. relocdmp    move.l  -4(a0),d3
  234.         beq.s   xlocdmp
  235.         exg.l   a0,d3       ;save
  236.         addq.l  #4,a0
  237.         bsr relocentr   ;reloc data pointer
  238.         move.l  d3,a0       ;restore
  239. xlocdmp     rts
  240. relocbi     move.w  msng_numblocks(a1),d0
  241.         move.l  a0,a3
  242. biloop      subq.w  #1,d0
  243.         bmi.s   xlocdmp
  244.         move.l  -(a3),a0
  245.         addq.l  #4,a0
  246.         bsr relocentr   ;BlockInfo ptr
  247.         tst.l   -(a0)
  248.         beq.s   biloop
  249.         move.l  (a0),a0
  250.         bsr relocentr   ;hldata
  251.         bsr relocentr   ;block name
  252.         bra.s   biloop
  253. ; take care of the new features of MMD2s
  254. relocmmd2sng    move.l  mmd_songinfo(a2),a0
  255.         lea msng_pseqs(a0),a0
  256.         bsr relocentr   ;playseqtable
  257.         bsr relocentr   ;sectiontable
  258.         bsr relocentr   ;trackvols
  259.         move.w  2(a0),d0    ;numpseqs
  260.         move.l  -12(a0),a0  ;get back to playseqtable
  261.         subq.w  #1,d0
  262. psqtblloop  bsr relocentr
  263.         dbf d0,psqtblloop
  264.         rts
  265.     ENDC
  266.  
  267.  
  268. ; -------- _ChannelOff: Turn off a channel -------------------------------
  269. _ChannelOff:    ;d0 = channel #
  270.         lea DB,a0
  271.         lea trackdataptrs-DB(a0),a1
  272.         lsl.w   #2,d0
  273.         adda.w  d0,a1
  274.         lsr.w   #2,d0
  275.         movea.l (a1),a1
  276.     IFNE    MIDI
  277.         move.b  trk_prevmidin(a1),d1    ;first: is it MIDI??
  278.         beq.s   notcomidi   ;not a midi note
  279. ; -------- TURN OFF MIDI TRACK -------------------------------------------
  280.         lea noteondata-DB(a0),a0
  281. choff_midi: clr.b   trk_prevmidin(a1)
  282.         move.b  d1,1(a0)
  283.         bmi.s   notamigatrk
  284.         move.b  trk_prevmidich(a1),(a0) ;prev midi channel
  285.         clr.b   2(a0)
  286.         or.b    #$90,(a0)       ;note off
  287.         moveq   #3,d0
  288.         bra.w   _AddMIDIData
  289.     ENDC
  290. notcomidi:  cmp.b   #4,d0
  291.         bge.s   notamigatrk
  292. ; -------- TURN OFF AMIGA-CHANNEL ----------------------------------------
  293.     IFNE    SYNTH
  294.         clr.l   trk_synthptr(a1)
  295.         clr.b   trk_synthtype(a1)
  296.     ENDC
  297.         clr.w   trk_soffset(a1)
  298.         moveq   #1,d1
  299.         lsl.w   d0,d1
  300.         move.w  d1,$dff096
  301. notamigatrk:    rts
  302.  
  303. ; -------- SoundOff: Turn off all channels -------------------------------
  304. SoundOff:   move.l  d2,-(sp)
  305.         moveq   #MAX_NUMTRACKS-1,d2
  306. SO_loop0    move.l  d2,d0
  307.         bsr.s   _ChannelOff
  308.         dbf d2,SO_loop0
  309.         clr.l   _module     ;play nothing
  310.         move.l  (sp)+,d2
  311. SO_rts      rts
  312.  
  313. ; -------- _PlayNote: The note playing routine ---------------------------
  314. _PlayNote:  ;d7(w) = trk #, d1 = note #, d3(w) = instr # a3 = addr of instr
  315. ; -------- CHECK INSTRUMENT (existence, type) ----------------------------
  316.         move.l  a3,d4
  317.         beq.s   SO_rts
  318.         moveq   #0,d4
  319.         bset    d7,d4   ;d4 is mask for this channel
  320.         movea.l mmd_smplarr(a2),a0
  321.         add.w   d3,d3           ;d3 = instr.num << 2
  322.         add.w   d3,d3
  323.         move.l  0(a0,d3.w),d5       ;get address of instrument
  324.     IFNE    MIDI
  325.         bne.s   inmem
  326.         tst.b   inst_midich(a3)     ;is MIDI channel set?
  327.     ENDC
  328.     IFNE    CHECK
  329.         beq.w   pnote_rts       ; NO!!!
  330.     ENDC
  331. ; -------- ADD TRANSPOSE -------------------------------------------------
  332. inmem       add.b   msng_playtransp(a4),d1  ;add play transpose
  333.         add.b   inst_strans(a3),d1  ;and instr. transpose
  334. ; -------- TURN OFF CHANNEL DMA, IF REQUIRED -----------------------------
  335.         cmp.b   #4,d7
  336.         bge.s   nodmaoff    ;track # >= 4: not an Amiga channel
  337.         move.l  d5,a1
  338.     IFNE    SYNTH
  339.         tst.l   d5
  340.         beq.s   stpdma
  341.         tst.b   trk_synthtype(a5)
  342.         ble.s   stpdma      ;prev. type = sample/hybrid
  343.         cmp.w   #-1,4(a1)   ;type == SYNTHETIC??
  344.         beq.s   nostpdma
  345.     ENDC
  346. stpdma:     move.w  d4,$dff096      ;stop this channel (dmacon)
  347. nostpdma:
  348.     IFNE    SYNTH
  349.         clr.l   trk_synthptr(a5)
  350.     ENDC
  351. nodmaoff:   subq.b  #1,d1
  352.     IFNE    MIDI
  353. ; -------- KILL PREVIOUS MIDI NOTE ---------------------------------------
  354.         move.b  trk_prevmidin(a5),d3    ;get prev. midi note
  355.         beq.s   noprevmidi
  356.         clr.b   trk_prevmidin(a5)
  357.         lea noteondata+2-DB(a6),a0
  358.         clr.b   (a0)
  359.         move.b  d3,-(a0)
  360.         bmi.s   noprevmidi
  361.         move.b  trk_prevmidich(a5),-(a0) ;prev midi channel
  362.         or.b    #$90,(a0)        ;note off
  363.         move.w  d1,-(sp)
  364.         moveq   #3,d0
  365.         bsr.w   _AddMIDId
  366.         move.w  (sp)+,d1
  367. noprevmidi:
  368. ; -------- IF MIDI NOTE, CALL MIDI NOTE ROUTINE --------------------------
  369.         tst.b   inst_midich(a3)
  370.         bne.w   handleMIDInote
  371.     ENDC
  372. ; -------- SET SOME AMIGA-CHANNEL PARAMETERS -----------------------------
  373.     IFNE    CHECK
  374.         cmp.w   #4,d7       ;track > 3???
  375.         bge.w   pnote_rts   ;no Amiga instruments here!!!
  376.     ENDC
  377. ; handle decay (for tracks 0 - 3 only!!)
  378.     IFNE    HOLD
  379.         clr.b   trk_fadespd(a5)     ;no fade yet..
  380.         move.b  trk_initdecay(a5),trk_decay(a5) ;set decay
  381.     ENDC
  382.         clr.w   trk_vibroffs(a5)    ;clr vibrato/tremolo offset
  383.         or.w    d4,dmaonmsk-DB(a6)
  384.         move.l  d5,a0
  385.     IFNE    SYNTH
  386. ; -------- IF SYNTH NOTE, CALL SYNTH ROUTINE -----------------------------
  387.         tst.w   4(a0)
  388.         bmi.w   handleSynthnote
  389.         clr.b   trk_synthtype(a5)
  390.     ENDC
  391. ; -------- CHECK NOTE RANGE ----------------------------------------------
  392. tlwtst0     tst.b   d1
  393.         bpl.s   notenot2low
  394.         add.b   #12,d1  ;note was too low, octave up
  395.         bra.s   tlwtst0
  396. notenot2low cmp.b   #62,d1
  397.         ble.s   endpttest
  398.         sub.b   #12,d1  ;note was too high, octave down
  399. endpttest
  400.         moveq   #0,d2
  401.         moveq   #0,d3
  402.         lea _periodtable+32-DB(a6),a1
  403.         move.b  trk_finetune(a5),d2 ;finetune value
  404.         add.b   d2,d2
  405.         add.b   d2,d2       ;multiply by 4...
  406.         ext.w   d2      ;extend
  407.         movea.l 0(a1,d2.w),a1   ;period table address
  408.     IFNE    IFFMOCT
  409.         move.w  4(a0),d0    ;Soitin-struct in a0
  410.         bne.s   gid_notnormal   ;note # in d1 (0 - ...)
  411.     ENDC
  412. gid_cont_ext    move.l  a1,trk_periodtbl(a5)
  413.         add.b   d1,d1
  414.         move.w  0(a1,d1.w),d5 ;put period to d5
  415.         move.l  a0,d0
  416.         addq.l  #6,d0       ;Skip structure
  417.         move.l  (a0),d1     ;length
  418.         add.l   d0,d1       ;sample end pointer
  419.         move.w  inst_repeat(a3),d2
  420.         move.w  inst_replen(a3),d3
  421.     IFNE    IFFMOCT
  422.         bra gid_setrept
  423. gid_addtable    dc.b    0,6,12,18,24,30
  424. gid_divtable    dc.b    31,7,3,15,63,127
  425. gid_notnormal   cmp.w   #7,d0
  426.         blt.s   gid_not_ext
  427.         suba.w  #48,a1
  428.         bra.s   gid_cont_ext
  429. gid_not_ext move.l  d7,-(sp)
  430.         moveq   #0,d7
  431.         move.w  d1,d7
  432.         divu    #12,d7  ;octave #
  433.         move.l  d7,d5
  434.         cmp.w   #6,d7   ;if oct > 5, oct = 5
  435.         blt.s   nohioct
  436.         moveq   #5,d7
  437. nohioct     swap    d5  ;note number in this oct (0-11) is in d5
  438.         move.l  (a0),d1
  439.         cmp.w   #6,d0
  440.         ble.s   nounrecit
  441.         moveq   #6,d0
  442. nounrecit   add.b   gid_addtable-1(pc,d0.w),d7
  443.         move.b  gid_divtable-1(pc,d0.w),d0
  444.         divu    d0,d1   ;get length of the highest octave
  445.         swap    d1
  446.         clr.w   d1
  447.         swap    d1
  448.         move.l  d1,d0       ;d0 and d1 = length of the 1st oct
  449.         move.w  inst_repeat(a3),d2
  450.         move.w  inst_replen(a3),d3
  451.         moveq   #0,d6
  452.         move.b  shiftcnt(pc,d7.w),d6
  453.         lsl.w   d6,d2
  454.         lsl.w   d6,d3
  455.         lsl.w   d6,d1
  456.         move.b  mullencnt(pc,d7.w),d6
  457.         mulu    d6,d0       ;offset of this oct from 1st oct
  458.         add.l   a0,d0       ;add base address to offset
  459.         addq.l  #6,d0       ;skip structure
  460.         add.l   d0,d1
  461.         move.l  a1,trk_periodtbl(a5)
  462.         add.b   octstart(pc,d7.w),d5
  463.         add.b   d5,d5
  464.         move.w  0(a1,d5.w),d5
  465.         move.l  (sp)+,d7
  466.         bra.s   gid_setrept
  467. shiftcnt:   dc.b    4,3,2,1,1,0,2,2,1,1,0,0,1,1,0,0,0,0
  468.         dc.b    3,3,2,2,1,0,5,4,3,2,1,0,6,5,4,3,2,1
  469. mullencnt:  dc.b    15,7,3,1,1,0,3,3,1,1,0,0,1,1,0,0,0,0
  470.         dc.b    7,7,3,3,1,0,31,15,7,3,1,0,63,31,15,7,3,1
  471. octstart:   dc.b    12,12,12,12,24,24,0,12,12,24,24,36,0,12,12,24,36,36
  472.         dc.b    0,12,12,24,24,24,12,12,12,12,12,12,12,12,12,12,12,12
  473.     ENDC
  474. gid_setrept add.l   d2,d2
  475.         add.l   d0,d2       ;rep. start pointer
  476.         cmp.w   #1,d3
  477.         bhi.s   gid_noreplen2
  478.         moveq   #0,d3       ;no repeat
  479.         bra.s   gid_cont
  480. gid_noreplen2   add.l   d3,d3
  481.         add.l   d2,d3       ;rep. end pointer
  482.  
  483. ; -------- CALCULATE START/END ADDRESSES ---------------------------------
  484. gid_cont    moveq   #0,d4
  485.         move.w  trk_soffset(a5),d4
  486.         add.l   d4,d0
  487.         cmp.l   d0,d1
  488.         bhi.s   pn_nooffsovf
  489.         sub.l   d4,d0
  490. pn_nooffsovf    movea.l trk_audioaddr(a5),a1 ;base of this channel's regs
  491.         move.l  d0,(a1)+        ;push ac_ptr
  492.         moveq   #0,d4
  493.         move.b  trk_previnstr(a5),d4
  494.         lea flags-DB(a6),a0
  495.         btst    #0,0(a0,d4.w)       ;test flags.SSFLG_LOOP
  496.         bne.s   repeat
  497.         
  498.         move.l  #_chipzero,trk_sampleptr(a5) ;pointer of zero word
  499.         move.w  #1,trk_samplelen(a5)    ;length: 1 word
  500.         sub.l   d0,d1
  501.         lsr.l   #1,d1           ;shift length right
  502.         move.w  d1,(a1)+        ;and push to ac_len
  503.         bra.s   retsn1
  504.  
  505. repeat      move.l  d2,trk_sampleptr(a5)
  506.         move.l  d3,d1
  507.         sub.l   d0,d1
  508.         lsr.l   #1,d1
  509.         move.w  d1,(a1)+    ;ac_len
  510.         sub.l   d2,d3
  511.         lsr.l   #1,d3
  512.         move.w  d3,trk_samplelen(a5)
  513.                 
  514. retsn1      move.w  d5,trk_prevper(a5)
  515.     IFNE    SYNTH
  516.         tst.b   trk_synthtype(a5)
  517.         bne.w   hSn2
  518.     ENDC
  519. pnote_rts   rts
  520.  
  521.     IFNE    MIDI
  522. ; -------- MIDI NOTE PLAYER ROUTINE --------------------------------------
  523. handleMIDInote:
  524.     IFNE    PLAYMMD0
  525.         cmp.b   #'1',3(a2)
  526.         bge.s   plr_mmd1_3
  527.         add.b   #24,d1
  528. plr_mmd1_3
  529.     ENDC
  530. ; -------- CHECK & SCALE VOLUME ------------------------------------------
  531.         move.b  trk_prevvol(a5),d2 ;temporarily save the volume
  532.         add.b   d2,d2       ;volume 0 - 63 => 0 - 127
  533.         subq.b  #1,d2       ;if 128 => 127
  534.         bpl.s   hmn_notvolu0
  535.         moveq   #0,d2
  536. hmn_notvolu0
  537.         moveq   #0,d5
  538. ; -------- CHECK MIDI CHANNEL --------------------------------------------
  539.         move.b  inst_midich(a3),d5 ;get midi chan of this instrument
  540.         bpl.s   hmn_nosmof  ;bit 7 clear
  541.         clr.b   trk_prevmidin(a5)   ;suppress note off!
  542.         bra.s   hmn_smof
  543. hmn_nosmof  move.b  d1,trk_prevmidin(a5)
  544. hmn_smof    and.b   #$1F,d5     ;clear all flag bits etc...
  545.         subq.b  #1,d5       ;from 1-16 to 0-15
  546.         move.b  d5,trk_prevmidich(a5)   ;save to prev midi channel
  547.  
  548. ; -------- CHECK MIDI PRESET ---------------------------------------------
  549.         moveq   #0,d0
  550.         move.b  trk_previnstr(a5),d0
  551.         add.w   d0,d0
  552.         lea ext_midipsets-DB(a6),a1
  553.         move.w  0(a1,d0.w),d0   ;get preset #
  554.         beq.s   nochgpres   ;zero = no preset
  555.         lea prevmidicpres-DB(a6),a1
  556.         adda.w  d5,a1
  557.         adda.w  d5,a1
  558.         cmp.w   (a1),d0     ;is this previous preset ??
  559.         beq.s   nochgpres   ;yes...no need to change
  560.         move.w  d0,(a1)     ;save preset to prevmidicpres
  561.         subq.w  #1,d0       ;sub 1 to get 0 - 127
  562.         btst    #6,inst_midich(a3)
  563.         bne.s   hmn_extpreset
  564. ; -------- PREPARE PRESET CHANGE COMMAND ---------------------------------
  565. hmn_ordpreset   lea preschgdata+1-DB(a6),a0
  566.         move.b  d0,(a0)     ;push the number to second byte
  567.         moveq   #2,d0
  568. hmn_sendpreset  move.b  #$c0,-(a0)  ;command: $C
  569.         or.b    d5,(a0)     ;"or" midi channel
  570.         move.w  d1,-(sp)
  571.         bsr.w   _AddMIDId
  572.         move.w  (sp)+,d1
  573.         tst.b   d2
  574.         beq.s   hmn_suppress    ;vol = 0, don't send NOTE ON
  575.  
  576. ; -------- PREPARE & SEND NOTE ON COMMAND --------------------------------
  577. nochgpres   lea bytesinnotebuff-DB(a6),a0
  578.         movea.l a0,a1
  579.         adda.w  (a0)+,a0
  580.         or.b    #$90,d5     ;MIDI: Note on
  581.         move.b  d5,(a0)+    ;MIDI msg Note on & channel
  582.         move.b  d1,(a0)+    ;MIDI msg note #
  583.         move.b  d2,(a0)     ;MIDI msg volume
  584.         beq.s   hmn_suppress    ;vol = 0 -> no note
  585.         addq.w  #3,(a1)
  586.         rts
  587. hmn_suppress    st  trk_prevmidin(a5)
  588.         rts
  589.  
  590. ; -------- HANDLE EXTENDED PRESET ----------------------------------------
  591. hmn_extpreset   cmp.w   #100,d0
  592.         blt.s   hmn_ordpreset
  593.         moveq   #99,d3
  594. hmn_loop100 sub.w   #100,d0
  595.         addq.b  #1,d3
  596.         cmp.w   #100,d0
  597.         bge.s   hmn_loop100
  598.         lea preschgdata+2-DB(a6),a0
  599.         move.b  d0,(a0)     ;push the <= 99 number
  600.         move.b  d3,-(a0)    ;push the >= 100 number
  601.         moveq   #3,d0
  602.         bra.s   hmn_sendpreset
  603.     ENDC
  604.  
  605.     IFNE    SYNTH
  606. ; -------- TRIGGER SYNTH NOTE, CLEAR PARAMETERS --------------------------
  607. handleSynthnote move.b  d1,trk_prevnote2(a5)
  608.         move.l  a0,trk_synthptr(a5)
  609.         cmp.w   #-2,4(a0)   ;HYBRID??
  610.         bne.s   hSn_nossn
  611.         st  trk_synthtype(a5)
  612.         movea.l 278(a0),a0  ;yep, get the waveform pointer
  613.         bra.w   tlwtst0     ;go and play it
  614. hSn_nossn:  move.b  #1,trk_synthtype(a5)
  615.         lea _periodtable+32-DB(a6),a1
  616.         move.b  trk_finetune(a5),d0 ;finetune value
  617.         add.b   d0,d0
  618.         add.b   d0,d0       ;multiple by 4...
  619.         ext.w   d0      ;extend
  620.         movea.l 0(a1,d0.w),a1   ;period table address
  621.         suba.w  #48,a1
  622.         move.l  a1,trk_periodtbl(a5) ;save table ptr for synth periods
  623.         add.w   d1,d1
  624.         move.w  0(a1,d1.w),d1
  625.         move.w  d1,trk_prevper(a5)
  626.         clr.l   trk_sampleptr(a5)
  627. hSn2:       lea trk_arpgoffs(a5),a1
  628.         clr.l   (a1)+
  629.         clr.l   (a1)+
  630.         clr.l   (a1)+
  631.         clr.l   (a1)+
  632.         clr.l   (a1)+
  633.         clr.l   (a1)+
  634.         move.l  #sinetable,(a1)+
  635.         clr.w   (a1)+
  636.         movea.l trk_synthptr(a5),a0
  637.                 move.w  18(a0),(a1)+
  638.                 clr.b   (a1)
  639.                 cmp.b   #$E,trk_cmd(a5)
  640.                 bne.s   hSn_nocmdE
  641.                 move.b  trk_cmdqual(a5),trk_wfcmd+1(a5)
  642. hSn_nocmdE  moveq   #64,d4
  643.         rts
  644.  
  645. synth_start move.w  trk_prevper(a5),d5
  646. synth_start2    move.l  a3,-(sp)    ;d0 = SynthPtr
  647.         move.l  d0,a0
  648.         movea.l trk_audioaddr(a5),a3    ;audio channel base address
  649. ; -------- SYNTHSOUND VOLUME SEQUENCE HANDLING ---------------------------
  650.         subq.b  #1,trk_volxcnt(a5)  ;decrease execute counter..
  651.         bgt.w   synth_wftbl     ;not 0...go to waveform
  652.         move.b  trk_initvolxspd(a5),trk_volxcnt(a5) ;reset counter
  653.         move.b  trk_volchgspd(a5),d0    ;volume change??
  654.         beq.s   synth_nochgvol      ;no.
  655.         add.b   trk_synvol(a5),d0   ;add previous volume
  656.         bpl.s   synth_voln2l        ;not negative
  657.         moveq   #0,d0           ;was negative => 0
  658. synth_voln2l    cmp.b   #$40,d0         ;too high??
  659.         ble.s   synth_voln2h        ;not 2 high.
  660.         moveq   #$40,d0         ;was 2 high => 64
  661. synth_voln2h    move.b  d0,trk_synvol(a5)   ;remember new...
  662. synth_nochgvol  move.l  trk_envptr(a5),d1   ;envelope pointer
  663.         beq.s   synth_novolenv
  664.         movea.l d1,a1
  665.         move.b  (a1)+,d0
  666.         add.b   #128,d0
  667.         lsr.b   #2,d0
  668.         move.b  d0,trk_synvol(a5)
  669.         addq.b  #1,trk_envcount(a5)
  670.         bpl.s   synth_endenv
  671.         clr.b   trk_envcount(a5)
  672.         move.l  trk_envrestart(a5),a1
  673. synth_endenv    move.l  a1,trk_envptr(a5)
  674. synth_novolenv  move.w  trk_volcmd(a5),d0   ;get table position ptr
  675.         tst.b   trk_volwait(a5)     ;WAI(t) active
  676.         beq.s   synth_getvolcmd     ;no
  677.         subq.b  #1,trk_volwait(a5)  ;yep, decr wait ctr
  678.         ble.s   synth_getvolcmd     ;0 => continue
  679.         bra.w   synth_wftbl     ;> 0 => still wait
  680. synth_inccnt    addq.b  #1,d0
  681. synth_getvolcmd addq.b  #1,d0           ;advance pointer
  682.         move.b  21(a0,d0.w),d1      ;get command
  683.         bmi.s   synth_cmd       ;negative = command
  684.         move.b  d1,trk_synvol(a5)   ;set synthvol
  685.         bra.w   synth_endvol        ;end of volume executing
  686. synth_cmd   and.w   #$000f,d1
  687.         add.b   d1,d1
  688.         move.w  synth_vtbl(pc,d1.w),d1
  689.         jmp syv(pc,d1.w)
  690. synth_vtbl  dc.w    syv_f0-syv,syv_f1-syv,syv_f2-syv,syv_f3-syv
  691.         dc.w    syv_f4-syv,syv_f5-syv,syv_f6-syv
  692.         dc.w    synth_endvol-syv,synth_endvol-syv,synth_endvol-syv
  693.         dc.w    syv_fa-syv,syv_ff-syv,synth_endvol-syv
  694.         dc.w    synth_endvol-syv,syv_fe-syv,syv_ff-syv
  695. ; -------- VOLUME SEQUENCE COMMANDS --------------------------------------
  696. syv
  697. syv_fe      move.b  22(a0,d0.w),d0      ;JMP
  698.         bra.s   synth_getvolcmd
  699. syv_f0      move.b  22(a0,d0.w),trk_initvolxspd(a5) ;change volume ex. speed
  700.         bra.s   synth_inccnt
  701. syv_f1      move.b  22(a0,d0.w),trk_volwait(a5) ;WAI(t)
  702.         addq.b  #1,d0
  703.         bra.s   synth_endvol
  704. syv_f3      move.b  22(a0,d0.w),trk_volchgspd(a5) ;set volume slide up
  705.         bra.s   synth_inccnt
  706. syv_f2      move.b  22(a0,d0.w),d1
  707.         neg.b   d1
  708.         move.b  d1,trk_volchgspd(a5) ;set volume slide down
  709.         bra.s   synth_inccnt
  710. syv_fa      move.b  22(a0,d0.w),trk_wfcmd+1(a5) ;JWS (jump wform sequence)
  711.         clr.b   trk_wfwait(a5)
  712.         bra.s   synth_inccnt
  713. syv_f4      move.b  22(a0,d0.w),d1
  714.         bsr.s   synth_getwf
  715.         clr.l   trk_envrestart(a5)
  716. syv_f4end   move.l  a1,trk_envptr(a5)
  717.         clr.b   trk_envcount(a5)
  718.         bra.w   synth_inccnt
  719. syv_f5      move.b  22(a0,d0.w),d1
  720.         bsr.s   synth_getwf
  721.         move.l  a1,trk_envrestart(a5)
  722.         bra.s   syv_f4end
  723. syv_f6      clr.l   trk_envptr(a5)
  724.         bra.w   synth_getvolcmd
  725. synth_getwf ext.w   d1  ;d1 = wform number, returns ptr in a1
  726.         add.w   d1,d1   ;create index
  727.         add.w   d1,d1
  728.         lea 278(a0),a1
  729.         adda.w  d1,a1
  730.         movea.l (a1),a1     ;get wform address
  731.         addq.l  #2,a1       ;skip length
  732.         rts
  733. syv_ff      subq.b  #1,d0
  734. synth_endvol    move.w  d0,trk_volcmd(a5)
  735. synth_wftbl
  736.     IFNE    RELVOL
  737.         moveq   #0,d0
  738.         move.b  trk_synvol(a5),d0
  739.         mulu    trk_trackvol(a5),d0
  740.         lsr.w   #8,d0
  741.         move.b  d0,trk_prevvol(a5) ;vol of this instr
  742.     ENDC
  743.     IFEQ    RELVOL
  744.         move.b  trk_synvol(a5),trk_prevvol(a5)
  745.     ENDC
  746.         adda.w  #158,a0
  747. ; -------- SYNTHSOUND WAVEFORM SEQUENCE HANDLING -------------------------
  748.         subq.b  #1,trk_wfxcnt(a5)   ;decr. wf speed counter
  749.         bgt.w   synth_arpeggio      ;not yet...
  750.         move.b  trk_initwfxspd(a5),trk_wfxcnt(a5) ;restore speed counter
  751.         move.w  trk_wfcmd(a5),d0    ;get table pos offset
  752.         move.w  trk_wfchgspd(a5),d1 ;CHU/CHD ??
  753.         beq.s   synth_tstwfwai      ;0 = no change
  754. wytanwet    add.w   trk_perchg(a5),d1   ;add value to current change
  755.         move.w  d1,trk_perchg(a5)   ;remember amount of change
  756. synth_tstwfwai  tst.b   trk_wfwait(a5)      ;WAI ??
  757.         beq.s   synth_getwfcmd      ;not waiting...
  758.         subq.b  #1,trk_wfwait(a5)   ;decr wait counter
  759.         beq.s   synth_getwfcmd      ;waiting finished
  760.         bra.w   synth_arpeggio      ;still sleep...
  761. synth_incwfc    addq.b  #1,d0
  762. synth_getwfcmd  addq.b  #1,d0           ;advance position counter
  763.         move.b  -9(a0,d0.w),d1      ;get command
  764.         bmi.s   synth_wfcmd     ;negative = command
  765.         ext.w   d1
  766.         add.w   d1,d1
  767.         add.w   d1,d1
  768.         movea.l 120(a0,d1.w),a1
  769.         move.w  (a1)+,ac_len(a3)    ;push waveform length
  770.         move.l  a1,ac_ptr(a3)       ;and the new pointer
  771.         bra.w   synth_wfend     ;no new commands now...
  772. synth_wfcmd and.w   #$000f,d1       ;get the right nibble
  773.         add.b   d1,d1           ;* 2
  774.         move.w  synth_wfctbl(pc,d1.w),d1
  775.         jmp syw(pc,d1.w)        ;jump to command
  776. synth_wfctbl    dc.w    syw_f0-syw,syw_f1-syw,syw_f2-syw,syw_f3-syw,syw_f4-syw
  777.         dc.w    syw_f5-syw,syw_f6-syw,syw_f7-syw,synth_wfend-syw
  778.         dc.w    synth_wfend-syw,syw_fa-syw,syw_ff-syw
  779.         dc.w    syw_fc-syw,synth_getwfcmd-syw,syw_fe-syw,syw_ff-syw
  780. ; -------- WAVEFORM SEQUENCE COMMANDS ------------------------------------
  781. syw
  782. syw_f7      move.b  -8(a0,d0.w),d1
  783.         ext.w   d1
  784.         add.w   d1,d1
  785.         add.w   d1,d1
  786.         movea.l 120(a0,d1.w),a1
  787.         addq.l  #2,a1
  788.         move.l  a1,trk_synvibwf(a5)
  789.         bra.s   synth_incwfc
  790. syw_fe      move.b  -8(a0,d0.w),d0      ;jump (JMP)
  791.         bra.s   synth_getwfcmd
  792. syw_fc      move.w  d0,trk_arpsoffs(a5) ;new arpeggio begin
  793.         move.w  d0,trk_arpgoffs(a5)
  794. synth_findare   addq.b  #1,d0
  795.         tst.b   -9(a0,d0.w)
  796.         bpl.s   synth_findare
  797.         bra.s   synth_getwfcmd
  798. syw_f0      move.b  -8(a0,d0.w),trk_initwfxspd(a5)  ;new waveform speed
  799.         bra synth_incwfc
  800. syw_f1      move.b  -8(a0,d0.w),trk_wfwait(a5)  ;wait waveform
  801.         addq.b  #1,d0
  802.         bra.s   synth_wfend
  803. syw_f4      move.b  -8(a0,d0.w),trk_synvibdep+1(a5) ;set vibrato depth
  804.         bra.w   synth_incwfc
  805. syw_f5      move.b  -8(a0,d0.w),trk_synthvibspd+1(a5) ;set vibrato speed
  806.         addq.b  #1,trk_synthvibspd+1(a5)
  807.         bra.w   synth_incwfc
  808. syw_f2      moveq   #0,d1           ;set slide down
  809.         move.b  -8(a0,d0.w),d1
  810. synth_setsld    move.w  d1,trk_wfchgspd(a5)
  811.         bra.w   synth_incwfc
  812. syw_f3      move.b  -8(a0,d0.w),d1      ;set slide up
  813.         neg.b   d1
  814.         ext.w   d1
  815.         bra.s   synth_setsld
  816. syw_f6      clr.w   trk_perchg(a5)      ;reset period
  817.         move.w  trk_prevper(a5),d5
  818.         bra.w   synth_getwfcmd
  819. syw_fa      move.b  -8(a0,d0.w),trk_volcmd+1(a5) ;JVS (jump volume sequence)
  820.         clr.b   trk_volwait(a5)
  821.         bra.w   synth_incwfc
  822. syw_ff      subq.b  #1,d0       ;pointer = END - 1
  823. synth_wfend move.w  d0,trk_wfcmd(a5)
  824. ; -------- HANDLE SYNTHSOUND ARPEGGIO ------------------------------------
  825. synth_arpeggio  move.w  trk_arpgoffs(a5),d0
  826.         beq.s   synth_vibrato
  827.         moveq   #0,d1
  828.         move.b  -8(a0,d0.w),d1
  829.         add.b   trk_prevnote2(a5),d1
  830.         movea.l trk_periodtbl(a5),a1    ;get period table
  831.         add.w   d1,d1
  832.         move.w  0(a1,d1.w),d5
  833.         addq.b  #1,d0
  834.         tst.b   -8(a0,d0.w)
  835.         bpl.s   synth_noarpres
  836.         move.w  trk_arpsoffs(a5),d0
  837. synth_noarpres  move.w  d0,trk_arpgoffs(a5)
  838. ; -------- HANDLE SYNTHSOUND VIBRATO -------------------------------------
  839. synth_vibrato   move.w  trk_synvibdep(a5),d1    ;get vibrato depth
  840.         beq.s   synth_rts       ;0 => no vibrato
  841.         move.w  trk_synviboffs(a5),d0   ;get offset
  842.         lsr.w   #4,d0           ;/ 16
  843.         and.w   #$1f,d0         ;sinetable offset (0-31)
  844.         movea.l trk_synvibwf(a5),a0
  845.         move.b  0(a0,d0.w),d0       ;get a byte
  846.         ext.w   d0          ;to word
  847.         muls    d1,d0           ;amplify (* depth)
  848.         asr.w   #8,d0           ;and divide by 64
  849.         add.w   d0,d5           ;add vibrato...
  850.         move.w  trk_synthvibspd(a5),d0  ;vibrato speed
  851.         add.w   d0,trk_synviboffs(a5)   ;add to offset
  852. synth_rts   add.w   trk_perchg(a5),d5
  853.         cmp.w   #113,d5         ;overflow??
  854.         bge.s   synth_pern2h
  855.         moveq   #113,d1
  856. synth_pern2h    move.l  (sp)+,a3
  857.         rts
  858.     ENDC
  859. sinetable   dc.b    0,25,49,71,90,106,117,125,127,125,117,106,90,71,49
  860.         dc.b    25,0,-25,-49,-71,-90,-106,-117,-125,-127,-125,-117
  861.         dc.b    -106,-90,-71,-49,-25,0
  862.  
  863. _IntHandler:    movem.l d2-d7/a2-a6,-(sp)
  864.     IFNE    CIAB|VBLANK
  865.         movea.l a1,a6   ;get data base address (int_Data)
  866.     ENDC
  867.     IFEQ    CIAB|VBLANK
  868.         lea DB,a6   ;don't expect a1 to contain DB address
  869.     ENDC
  870.         tst.b   bpmcounter-DB(a6)
  871.         bmi.s   plr_nobpm
  872.         subq.b  #1,bpmcounter-DB(a6)
  873.         ble.s   plr_bpmcnt0
  874.         bra.w   plr_exit
  875. plr_bpmcnt0 move.b  #4,bpmcounter-DB(a6)
  876. plr_nobpm   movea.l _module-DB(a6),a2
  877.         move.l  a2,d0
  878.         beq.w   plr_exit
  879.     IFNE    MIDI
  880.         clr.b   lastcmdbyte-DB(a6)  ;no MIDI optimization
  881.     ENDC
  882.         tst.w   mmd_pstate(a2)
  883.         beq.w   plr_exit
  884.     IFNE    MIDI
  885.         clr.l   dmaonmsk-DB(a6)
  886.     ENDC
  887.     IFEQ    MIDI
  888.         clr.w   dmaonmsk-DB(a6)
  889.     ENDC
  890.         movea.l mmd_songinfo(a2),a4
  891.         moveq   #0,d3
  892.         move.b  mmd_counter(a2),d3
  893.         addq.b  #1,d3
  894.         cmp.b   msng_tempo2(a4),d3
  895.         bge.s   plr_pnewnote    ;play new note
  896.         move.b  d3,mmd_counter(a2)
  897.         bne.w   plr_fxtime  ;do just fx
  898. ; --- new note!!
  899. plr_pnewnote:   clr.b   mmd_counter(a2)
  900.         tst.w   blkdelay-DB(a6)
  901.         beq.s   plr_noblkdelay
  902.         subq.w  #1,blkdelay-DB(a6)
  903.         bne.w   nonewnote
  904. ; --- now start to play it
  905. plr_noblkdelay  move.w  mmd_pblock(a2),d0
  906.         movea.l mmd_blockarr(a2),a0
  907.         add.w   d0,d0
  908.         add.w   d0,d0
  909.         movea.l 0(a0,d0.w),a1   ;block...
  910.         move.w  mmd_pline(a2),d0
  911.     IFNE    PLAYMMD0
  912.         cmp.b   #'1',3(a2)  ;check ID type
  913.         bge.s   plr_mmd1_0
  914.         move.w  d0,d1
  915.         add.w   d0,d0
  916.         add.w   d1,d0       ;d0 = d0 * 3
  917.         clr.l   numtracks-DB(a6)
  918.         move.b  (a1)+,numtracks+1-DB(a6)
  919.         move.b  (a1),numlines+1-DB(a6)
  920.         mulu    numtracks-DB(a6),d0
  921.         pea 1(a1,d0.w)
  922.         bra.s   plr_begloop
  923. plr_mmd1_0
  924.     ENDC
  925.         add.w   d0,d0
  926.         add.w   d0,d0       ;d0 = d0 * 4
  927.         mulu    (a1),d0     ;numtracks * d0
  928.         pea 8(a1,d0.l)  ;address of the current note
  929.         move.w  (a1)+,numtracks-DB(a6)
  930.         move.w  (a1),numlines-DB(a6)
  931. plr_begloop moveq   #0,d7       ;number of track
  932.         moveq   #0,d4
  933.         pea trackdataptrs-DB(a6)
  934. plr_loop0:  moveq   #0,d5
  935.         move.l  (sp),a1
  936.         movea.l (a1)+,a5    ;get address of this track's struct
  937.         move.l  a1,(sp)
  938. ; ---------------- get the note numbers
  939.         moveq   #0,d3
  940.         move.l  4(sp),a1
  941.     IFNE    PLAYMMD0
  942.         cmp.b   #'1',3(a2)
  943.         bge.s   plr_mmd1_1
  944.         move.b  (a1)+,d5
  945.         move.b  (a1)+,d6
  946.         move.b  (a1)+,trk_cmdqual(a5)
  947.         move.b  d6,d3
  948.         and.w   #$0F,d6
  949.         lsr.b   #4,d3
  950.         bclr    #7,d5
  951.         beq.s   plr_bseti4
  952.         bset    #4,d3
  953. plr_bseti4  bclr    #6,d5
  954.         beq.s   plr_bseti5
  955.         bset    #5,d3
  956. plr_bseti5  bra.s   plr_nngok
  957. plr_mmd1_1
  958.     ENDC
  959.         move.b  (a1)+,d5    ;get the number of this note
  960.         bpl.s   plr_nothinote
  961.         moveq   #0,d5
  962. plr_nothinote   move.b  (a1)+,d3    ;instrument number
  963.         move.b  (a1)+,d6    ;cmd number
  964.         and.w   #$1F,d6     ;recognize only cmds 00 - 1F
  965.         move.b  (a1)+,trk_cmdqual(a5)   ;databyte (qualifier)
  966. plr_nngok   move.l  a1,4(sp)
  967. ; ---------------- check if there's an instrument number
  968.         and.w   #$3F,d3
  969.         beq.s   noinstnum
  970. ; ---------------- finally, save the number
  971.         subq.b  #1,d3
  972.         move.b  d3,trk_previnstr(a5) ;remember instr. number!
  973.     IFNE    HOLD
  974.         lea holdvals-DB(a6),a0
  975.         adda.w  d3,a0
  976.         move.b  (a0),trk_inithold(a5)
  977.         move.b  63(a0),trk_initdecay(a5)
  978.         move.b  126(a0),trk_finetune(a5)
  979.     ENDC
  980.     IFEQ    HOLD
  981.         lea finetunes-DB(a6),a0
  982.         move.b  0(a0,d3.w),trk_finetune(a5)
  983.     ENDC
  984.         asl.w   #3,d3
  985.         lea 0(a4,d3.w),a3   ;a3 contains now address of it
  986.         move.l  a3,trk_previnstra(a5)
  987.         moveq   #0,d0
  988. ; ---------------- get volume and make it relative (1 - 100 %)
  989.     IFNE    RELVOL
  990.         move.b  inst_svol(a3),d0
  991.         mulu    trk_trackvol(a5),d0
  992.         lsr.w   #8,d0
  993.         move.b  d0,trk_prevvol(a5) ;vol of this instr
  994.     ENDC
  995.     IFEQ    RELVOL
  996.         move.b  inst_svol(a3),trk_prevvol(a5)
  997.     ENDC
  998. ; ---------------- remember transpose
  999.         move.b  inst_strans(a3),trk_stransp(a5)
  1000.         clr.w   trk_soffset(a5)     ;sample offset
  1001. ; ---------------- check the commands
  1002. noinstnum   move.b  d6,trk_cmd(a5)  ;save the effect number
  1003.         beq.w   fx  ;no effect
  1004.         move.b  trk_cmdqual(a5),d4  ;get qualifier...
  1005.         add.b   d6,d6   ;* 2
  1006.         move.w  f_table(pc,d6.w),d0
  1007.         jmp fst(pc,d0.w)
  1008. f_table     dc.w    fx-fst,fx-fst,fx-fst,f_03-fst,fx-fst,fx-fst,fx-fst,fx-fst
  1009.         dc.w    f_08-fst,f_09-fst,fx-fst,f_0b-fst,f_0c-fst,fx-fst,f_0e-fst,f_0f-fst
  1010.         dc.w    fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,f_15-fst,f_16-fst,fx-fst
  1011.         dc.w    fx-fst,f_19-fst,fx-fst,fx-fst,f_1c-fst,f_1d-fst,fx-fst,f_1f-fst
  1012. fst
  1013. ; ---------------- tempo (F)
  1014. f_0f        tst.b   d4      ;test effect qual..
  1015.         beq fx0fchgblck ;if effect qualifier (last 2 #'s)..
  1016.         cmp.b   #$f0,d4     ;..is zero, go to next block
  1017.         bhi.s   fx0fspecial ;if it's F1-FF something special
  1018. ; ---------------- just an ordinary "change tempo"-request
  1019.     IFNE    CIAB
  1020.         moveq   #0,d0       ;will happen!!!
  1021.         move.b  d4,d0
  1022.         move.w  d0,msng_deftempo(a4)
  1023.         bsr _SetTempo   ;change The Tempo
  1024.     ENDC
  1025.         bra.w   fx
  1026. ; ---------------- no, it was FFx, something special will happen!!
  1027. fx0fspecial:    cmp.b   #$f2,d4
  1028.         beq.s   f_1f
  1029.         cmp.b   #$f4,d4
  1030.         beq.s   f_1f
  1031.         cmp.b   #$f5,d4
  1032.         bne.s   isfxfe
  1033. ; ---------------- FF2 (or 1Fxx)
  1034. f_1f        move.b  d5,(a5) ; save the note number
  1035.         moveq   #0,d5   ; clear the number for awhile
  1036.     IFNE    HOLD
  1037.         move.b  trk_inithold(a5),trk_noteoffcnt(a5) ;initialize hold
  1038.         bne.w   plr_endloop0        ;not 0 -> OK
  1039.         st  trk_noteoffcnt(a5)  ;0 -> hold = 0xff (-1)
  1040.     ENDC
  1041.         bra.w   plr_endloop0
  1042. isfxfe:     cmp.b   #$fe,d4
  1043.         bne.s   notcmdfe
  1044. ; ---------------- it was FFE, stop playing
  1045.         clr.w   mmd_pstate(a2)
  1046.     IFNE    CIAB
  1047.         movea.l craddr-DB(a6),a0
  1048.         bclr    #0,(a0)
  1049.     ENDC
  1050.         bsr.w   SoundOff
  1051.         addq.l  #8,sp
  1052.         bra.w   plr_exit
  1053. notcmdfe:   cmp.b   #$fd,d4 ;change period
  1054.         bne.s   isfxff
  1055. ; ---------------- FFD, change the period, don't replay the note
  1056.     IFNE    CHECK
  1057.         cmp.w   #4,d7
  1058.         bge.w   fx
  1059.     ENDC
  1060.         movea.l trk_periodtbl(a5),a0
  1061.         subq.b  #1,d5
  1062.         bmi.w   plr_endloop0
  1063.         add.b   msng_playtransp(a4),d5
  1064.         add.b   trk_stransp(a5),d5
  1065.         add.w   d5,d5
  1066.         bmi plr_endloop0
  1067.         move.w  0(a0,d5.w),trk_prevper(a5)
  1068.         moveq   #0,d5
  1069.         bra.w   fx
  1070. isfxff:     cmp.b   #$ff,d4
  1071.         bne.w   fx
  1072.         move.w  d7,d0
  1073.         bsr.w   _ChannelOff
  1074.         bra.w   fx
  1075. ; ---------------- F00, called Pattern Break in ST
  1076. fx0fchgblck:    move.b  #1,nextblock-DB(a6)
  1077.         bra.w   fx
  1078. ; ---------------- was not Fxx
  1079. f_0e        cmp.b   #3,d7
  1080.         bgt.w   fx
  1081.         move.b  d4,trk_wfcmd+1(a5) ;set waveform command position ptr
  1082.         bra.w   fx
  1083. ; ---------------- change volume
  1084. f_0c        move.b  d4,d0
  1085.         bpl.s   plr_nosetdefvol
  1086.         and.b   #$7F,d0
  1087.     IFNE    CHECK
  1088.         cmp.b   #64,d0
  1089.         bgt.s   go_nocmd
  1090.     ENDC
  1091.         moveq   #0,d1
  1092.         move.b  trk_previnstr(a5),d1
  1093.         asl.w   #3,d1
  1094.         move.b  d0,inst_svol(a4,d1.w)
  1095.         bra.s   plr_setvol
  1096. plr_nosetdefvol btst    #4,msng_flags(a4)   ;look at flags
  1097.         bne.s   volhex
  1098.         lsr.b   #4,d0       ;get number from left
  1099.         mulu    #10,d0      ;number of tens
  1100.         move.b  d4,d1       ;get again
  1101.         and.b   #$0f,d1     ;this time don't get tens
  1102.         add.b   d1,d0       ;add them
  1103. volhex:
  1104.     IFNE    CHECK
  1105.         cmp.b   #64,d0
  1106.         bhi.s   go_nocmd
  1107.     ENDC
  1108. plr_setvol
  1109.     IFNE    RELVOL
  1110.         mulu    trk_trackvol(a5),d0
  1111.         lsr.w   #8,d0
  1112.     ENDC
  1113.         move.b  d0,trk_prevvol(a5)
  1114. go_nocmd    bra.w   fx
  1115. ; ---------------- tempo2 change?
  1116. f_09
  1117.     IFNE    CHECK
  1118.         and.b   #$1F,d4
  1119.         bne.s   fx9chk
  1120.         moveq   #$20,d4
  1121.     ENDC
  1122. fx9chk:     move.b  d4,msng_tempo2(a4)
  1123.         bra fx
  1124. ; ---------------- finetune
  1125. f_15
  1126.     IFNE    CHECK
  1127.         cmp.b   #7,d4
  1128.         bgt fx
  1129.         cmp.b   #-8,d4
  1130.         blt fx
  1131.     ENDC
  1132.         move.b  d4,trk_finetune(a5)
  1133.         bra fx
  1134. ; ---------------- repeat loop
  1135. f_16        tst.b   d4
  1136.         bne.s   plr_dorpt
  1137.         move.w  mmd_pline(a2),rptline-DB(a6)
  1138.         bra fx
  1139. plr_dorpt   tst.w   rptcounter-DB(a6)
  1140.         beq.s   plr_newrpt
  1141.         subq.w  #1,rptcounter-DB(a6)
  1142.         beq fx
  1143.         bra.s   plr_setrptline
  1144. plr_newrpt  move.b  d4,rptcounter+1-DB(a6)
  1145. plr_setrptline  move.w  rptline-DB(a6),d0
  1146.         addq.w  #1,d0
  1147.         move.w  d0,nextblockline-DB(a6)
  1148.         bra fx
  1149. ; ---------------- preset change
  1150. f_1c
  1151.     IFNE    CHECK
  1152.         cmp.b   #$80,d4
  1153.         bhi fx
  1154.     ENDC
  1155.         moveq   #0,d1
  1156.         move.b  trk_previnstr(a5),d1
  1157.         add.w   d1,d1
  1158.         lea ext_midipsets-DB(a6),a0
  1159.         ext.w   d4
  1160.         move.w  d4,0(a0,d1.w)   ;set MIDI preset
  1161.         bra.s   fx
  1162. ; ---------------- note off time set??
  1163. f_08
  1164.     IFNE    HOLD
  1165.         move.b  d4,d0
  1166.         lsr.b   #4,d4       ;extract left  nibble
  1167.         and.b   #$0f,d0     ; "   "  right  "  "
  1168.         move.b  d4,trk_initdecay(a5)    ;left = decay
  1169.         move.b  d0,trk_inithold(a5) ;right = hold
  1170.     ENDC
  1171.         bra.s   fx
  1172. ; ---------------- sample begin offset
  1173. f_19        lsl.w   #8,d4
  1174.         move.w  d4,trk_soffset(a5)
  1175.         bra.s   fx
  1176. ; ---------------- cmd Bxx, "position jump"
  1177. f_0b
  1178.     IFNE    CHECK
  1179.         cmp.b   #'2',3(a2)
  1180.         beq.s   chk0b_mmd2
  1181.         cmp.w   msng_songlen(a4),d4
  1182.         bhi.s   fx
  1183.         bra.s   chk0b_end
  1184. chk0b_mmd2  move.w  mmd_pseq(a2),d0     ;get seq number
  1185.         movea.l msng_pseqs(a4),a1   ;ptr to playseqs
  1186.         movea.l 0(a1,d0.w),a0       ;a0 = ptr to curr PlaySeq
  1187.         cmp.w   40(a0),d4       ;test song length
  1188.         bhi.s   fx
  1189. chk0b_end
  1190.     ENDC
  1191.         move.w  d4,mmd_pseqnum(a2)
  1192.         st  nextblock-DB(a6)    ; = 1
  1193.         bra.s   fx
  1194. ; ---------------- cmd 1Dxx, jump to next seq, line # specified
  1195. f_1d        move.w  #$1ff,nextblock-DB(a6)
  1196.         addq.w  #1,d4
  1197.         move.w  d4,nextblockline-DB(a6)
  1198.         bra.s   fx
  1199. ; ---------------- try portamento (3)
  1200. f_03
  1201.     IFNE    CHECK
  1202.         cmp.w   #4,d7
  1203.         bge.s   plr_endloop0
  1204.     ENDC
  1205.         subq.b  #1,d5       ;subtract note number
  1206.         bmi.s   plr_setfx3spd   ;0 -> set new speed
  1207. plr_fx3note:    movea.l trk_periodtbl(a5),a0
  1208.         add.b   msng_playtransp(a4),d5  ;play transpose
  1209.         add.b   trk_stransp(a5),d5  ;and instrument transpose
  1210.         bmi.s   plr_endloop0
  1211.         add.w   d5,d5
  1212.         move.w  0(a0,d5.w),trk_porttrgper(a5) ;period of this note is the target
  1213. plr_setfx3spd:  tst.b   d4      ;qual??
  1214.         beq.s   plr_endloop0    ;0 -> do nothing
  1215.         move.b  d4,trk_prevportspd(a5)  ;store speed
  1216.         bra.s   plr_endloop0        ;don't play this one
  1217. ; ---------------- play or not to play??
  1218. fx      tst.b   d5          ;play a note?
  1219.         beq.s   plr_endloop0        ;no.
  1220. ; ---------------- play
  1221.         move.b  d5,(a5)
  1222.         move.w  d5,d1
  1223.         moveq   #0,d3
  1224.         move.b  trk_previnstr(a5),d3    ;instr #
  1225.         movea.l trk_previnstra(a5),a3   ;instr data address
  1226.     IFNE    HOLD
  1227.         move.b  trk_inithold(a5),trk_noteoffcnt(a5) ;initialize hold
  1228.         bne.s   plr_nohold0     ;not 0 -> OK
  1229.         st  trk_noteoffcnt(a5)  ;0 -> hold = 0xff (-1)
  1230.     ENDC
  1231. ; ---------------- and finally:
  1232. plr_nohold0 bsr _PlayNote
  1233. ; ---------------- end of loop: handle next track, or quit
  1234. plr_endloop0:   addq.b  #1,d7
  1235.         cmp.w   numtracks-DB(a6),d7
  1236.         blt.w   plr_loop0
  1237.         addq.l  #8,sp           ;trackdataptrs / note ptr
  1238. ; and advance song pointers
  1239.         lea nextblock-DB(a6),a3
  1240.         move.w  nextblockline-DB(a6),d1
  1241.         beq.s   plr_advlinenum
  1242.         clr.w   nextblockline-DB(a6)
  1243.         subq.w  #1,d1
  1244.         bra.s   plr_linenumset
  1245. plr_advlinenum  move.w  mmd_pline(a2),d1    ;get current line #
  1246.         addq.w  #1,d1           ;advance line number
  1247. plr_linenumset  cmp.w   numlines-DB(a6),d1  ;advance block?
  1248.         bhi.s   plr_chgblock        ;yes.
  1249.         tst.b   (a3)            ;command F00/1Dxx?
  1250.         beq plr_nochgblock      ;no, don't change block
  1251. ; -------- CHANGE BLOCK? -------------------------------------------------
  1252. plr_chgblock    tst.b   nxtnoclrln-DB(a6)
  1253.         bne.s   plr_noclrln
  1254.         moveq   #0,d1           ;clear line number
  1255. plr_noclrln tst.w   mmd_pstate(a2)      ;play block or play song
  1256.         bpl plr_nonewseq        ;play block only...
  1257.         cmp.b   #'2',3(a2)      ;MMD2?
  1258.         bne.s   plr_noMMD2_0
  1259. ; ********* BELOW CODE FOR MMD2 ONLY ************************************
  1260. ; -------- CHANGE SEQUENCE -----------------------------------------------
  1261. plr_skipseq move.w  mmd_pseq(a2),d0     ;actually stored as << 2
  1262.         movea.l msng_pseqs(a4),a1
  1263.         movea.l 0(a1,d0.w),a0
  1264.         move.w  mmd_pseqnum(a2),d0  ;get play sequence number
  1265.         tst.b   (a3)
  1266.         bmi.s   plr_noadvseq        ;Bxx sets nextblock to -1
  1267.         addq.w  #1,d0           ;advance sequence number
  1268. plr_noadvseq    cmp.w   40(a0),d0       ;is this the highest seq number??
  1269.         blt.s   plr_notagain        ;no.
  1270. ; -------- CHANGE SECTION ------------------------------------------------
  1271.         move.w  mmd_psecnum(a2),d0  ;get section number
  1272.         addq.w  #1,d0           ;increase..
  1273.         cmp.w   msng_songlen(a4),d0 ;highest section?
  1274.         blt.s   plr_nohisec
  1275.         moveq   #0,d0           ;yes.
  1276. plr_nohisec move.w  d0,mmd_psecnum(a2)  ;push back.
  1277.         add.w   d0,d0
  1278.         movea.l msng_sections(a4),a0    ;section table
  1279.         move.w  0(a0,d0.w),d0       ;new playseqlist number
  1280.         add.w   d0,d0
  1281.         add.w   d0,d0
  1282.         move.w  d0,mmd_pseq(a2)
  1283.         movea.l 0(a1,d0.w),a0       ;a0 = ptr to new PlaySeq
  1284.         moveq   #0,d0           ;playseq OFFSET = 0
  1285. ; -------- FETCH BLOCK NUMBER FROM SEQUENCE ------------------------------
  1286. plr_notagain    move.w  d0,mmd_pseqnum(a2)  ;remember new playseq pos
  1287.         add.w   d0,d0
  1288.         move.w  42(a0,d0.w),d0      ;get number of the block
  1289.         bpl.s   plr_changeblk   ;neg. values for future expansion
  1290.         bra.s   plr_skipseq ;(skip them)
  1291. ; ********* BELOW CODE FOR MMD0/MMD1 ONLY *******************************
  1292. plr_noMMD2_0    move.w  mmd_pseqnum(a2),d0  ;get play sequence number
  1293.         tst.b   (a3)
  1294.         bmi.s   plr_noadvseq_b      ;Bxx sets nextblock to -1
  1295.         addq.w  #1,d0           ;advance sequence number
  1296. plr_noadvseq_b  cmp.w   msng_songlen(a4),d0 ;is this the highest seq number??
  1297.         blt.s   plr_notagain_b      ;no.
  1298.         moveq   #0,d0           ;yes: restart song
  1299. plr_notagain_b  move.b  d0,mmd_pseqnum+1(a2)    ;remember new playseq-#
  1300.         lea msng_playseq(a4),a0 ;offset of sequence table
  1301.         move.b  0(a0,d0.w),d0       ;get number of the block
  1302. ; ********* BELOW CODE FOR BOTH FORMATS *********************************
  1303. plr_changeblk
  1304.     IFNE    CHECK
  1305.         cmp.w   msng_numblocks(a4),d0   ;beyond last block??
  1306.         blt.s   plr_nolstblk        ;no..
  1307.         moveq   #0,d0           ;play block 0
  1308.     ENDC
  1309. plr_nolstblk    move.w  d0,mmd_pblock(a2)   ;store block number
  1310. plr_nonewseq    clr.w   (a3)            ;clear this if F00 set it
  1311. plr_nochgblock  move.w  d1,mmd_pline(a2)    ;set new line number
  1312.  
  1313.     IFNE    HOLD
  1314.         lea trackdataptrs-DB(a6),a5
  1315.         movea.l mmd_blockarr(a2),a0
  1316.         move.w  mmd_pblock(a2),d0
  1317.         add.w   d0,d0
  1318.         add.w   d0,d0
  1319.         movea.l 0(a0,d0.w),a1   ;block...
  1320.         move.w  mmd_pline(a2),d0
  1321.         move.b  msng_tempo2(a4),d3  ;interrupts/note
  1322.     IFNE    PLAYMMD0
  1323.         cmp.b   #'1',3(a2)
  1324.         bge.s   plr_mmd1_2
  1325.         move.b  (a1),d7         ;# of tracks
  1326.         move.w  d0,d1
  1327.         add.w   d0,d0   ;d0 * 2
  1328.         add.w   d1,d0   ;+ d0 = d0 * 3
  1329.         mulu    d7,d0
  1330.         lea 2(a1,d0.w),a3
  1331.         subq.b  #1,d7
  1332. plr_chkholdb    movea.l (a5)+,a1        ;track data
  1333.         tst.b   trk_noteoffcnt(a1)  ;hold??
  1334.         bmi.s   plr_holdendb        ;no.
  1335.         move.b  (a3),d1         ;get the 1st byte..
  1336.         bne.s   plr_hold1b
  1337.         move.b  1(a3),d1
  1338.         and.b   #$f0,d1
  1339.         beq.s   plr_holdendb        ;don't hold
  1340.         bra.s   plr_hold2b
  1341. plr_hold1b  and.b   #$3f,d1         ;note??
  1342.         beq.s   plr_hold2b      ;no, cont hold..
  1343.         move.b  1(a3),d1
  1344.         and.b   #$0f,d1         ;get cmd
  1345.         subq.b  #3,d1           ;is there command 3 (slide)
  1346.         bne.s   plr_holdendb        ;no -> end holding
  1347. plr_hold2b  add.b   d3,trk_noteoffcnt(a1)   ;continue holding...
  1348. plr_holdendb    addq.l  #3,a3       ;next note
  1349.         dbf d7,plr_chkholdb
  1350.         bra.s   nonewnote
  1351. plr_mmd1_2
  1352.     ENDC
  1353.         move.w  (a1),d7     ;# of tracks
  1354.         add.w   d0,d0
  1355.         add.w   d0,d0   ;d0 = d0 * 4
  1356.         mulu    d7,d0
  1357.         lea 8(a1,d0.l),a3
  1358.         subq.b  #1,d7
  1359. plr_chkhold movea.l (a5)+,a1        ;track data
  1360.         tst.b   trk_noteoffcnt(a1)  ;hold??
  1361.         bmi.s   plr_holdend     ;no.
  1362.         move.b  (a3),d1         ;get the 1st byte..
  1363.         bne.s   plr_hold1
  1364.         move.b  1(a3),d0
  1365.         and.b   #$3F,d0
  1366.         beq.s   plr_holdend     ;don't hold
  1367.         bra.s   plr_hold2
  1368. plr_hold1   and.b   #$7f,d1         ;note??
  1369.         beq.s   plr_hold2       ;no, cont hold..
  1370.         move.b  2(a3),d1
  1371.         subq.b  #3,d1           ;is there command 3 (slide)
  1372.         bne.s   plr_holdend     ;no -> end holding
  1373. plr_hold2   add.b   d3,trk_noteoffcnt(a1)   ;continue holding...
  1374. plr_holdend addq.l  #4,a3       ;next note
  1375.         dbf d7,plr_chkhold
  1376.     ENDC    
  1377. nonewnote   moveq   #0,d3
  1378.         move.b  mmd_counter(a2),d3
  1379. plr_fxtime  lea trackdataptrs-DB(a6),a3
  1380.         moveq   #0,d7   ;clear track count
  1381. plr_loop1   movea.l (a3)+,a5
  1382.         moveq   #0,d4
  1383.         moveq   #0,d5
  1384.         moveq   #0,d6
  1385.         move.b  trk_cmd(a5),d6  ;get the fx number
  1386.         move.b  trk_cmdqual(a5),d4  ;and the last 2 #'s
  1387.     IFNE    MIDI
  1388.         tst.b   trk_prevmidin(a5)   ;is it MIDI??
  1389.         bne.w   midicmds
  1390.     ENDC
  1391.         cmp.w   #4,d7
  1392.     IFNE    MIDI
  1393.         bge.w   midicmds    ;no non-MIDI effects in tracks >= 4
  1394.     ENDC
  1395.     IFEQ    MIDI
  1396.         bge.w   endl
  1397.     ENDC
  1398.     IFNE    HOLD
  1399.         tst.b   trk_noteoffcnt(a5)
  1400.         bmi.s   plr_nowaitoff
  1401.         subq.b  #1,trk_noteoffcnt(a5)
  1402.         bpl.s   plr_nowaitoff
  1403.     IFNE    SYNTH
  1404.         tst.b   trk_synthtype(a5)       ;synth/hybrid??
  1405.         beq.s   plr_nosyndec
  1406.         move.b  trk_decay(a5),trk_volcmd+1(a5)  ;set volume command pointer
  1407.         clr.b   trk_volwait(a5)         ;abort WAI
  1408.         bra.s   plr_nowaitoff
  1409.     ENDC
  1410. plr_nosyndec:   move.b  trk_decay(a5),trk_fadespd(a5)   ;set fade...
  1411.         bne.s   plr_nowaitoff           ;if > 0, don't stop sound
  1412.         bset    d7,d5
  1413.         move.w  d5,$dff096          ;shut DMA...
  1414.         moveq   #0,d5
  1415.     ENDC
  1416. plr_nowaitoff:  
  1417.     IFNE    HOLD
  1418.         move.b  trk_fadespd(a5),d0  ;fade??
  1419.         beq.s   plr_nofade  ;no.
  1420.         sub.b   d0,trk_prevvol(a5)
  1421.         bpl.s   plr_nofade
  1422.         clr.b   trk_prevvol(a5)
  1423.         clr.b   trk_fadespd(a5)     ;fade no more
  1424.     ENDC
  1425. plr_nofade  add.b   d6,d6   ;* 2
  1426.         move.w  fx_table(pc,d6.w),d0
  1427.         jmp fxs(pc,d0.w)
  1428. fx_table    dc.w    fx_00-fxs,fx_01-fxs,fx_02-fxs,fx_03-fxs,fx_04-fxs
  1429.         dc.w    fx_05-fxs,fx_06-fxs,fx_07-fxs,fx_xx-fxs,fx_xx-fxs
  1430.         dc.w    fx_0a-fxs,fx_xx-fxs,fx_xx-fxs,fx_0d-fxs,fx_xx-fxs
  1431.         dc.w    fx_0f-fxs
  1432.         dc.w    fx_10-fxs,fx_11-fxs,fx_12-fxs,fx_13-fxs,fx_14-fxs
  1433.         dc.w    fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_18-fxs,fx_xx-fxs
  1434.         dc.w    fx_1a-fxs,fx_1b-fxs,fx_xx-fxs,fx_xx-fxs,fx_1e-fxs
  1435.         dc.w    fx_1f-fxs
  1436. fxs:
  1437. ;   **************************************** Effect 01 ******
  1438. fx_01:      tst.b   d3
  1439.         bne.s   fx_01nocnt0
  1440.         btst    #5,msng_flags(a4)   ;FLAG_STSLIDE??
  1441.         bne fx_xx
  1442. fx_01nocnt0 sub.w   d4,trk_prevper(a5)
  1443.         move.w  trk_prevper(a5),d5
  1444.         cmp.w   #113,d5
  1445.         bge plr_newper
  1446.         move.w  #113,d5
  1447.         move.w  d5,trk_prevper(a5)
  1448.         bra plr_newper
  1449. ;   **************************************** Effect 11 ******
  1450. fx_11       tst.b   d3
  1451.         bne fx_xx
  1452.         sub.w   d4,trk_prevper(a5)
  1453.         move.w  trk_prevper(a5),d5
  1454.         bra plr_newper
  1455. ;   **************************************** Effect 02 ******
  1456. fx_02:      tst.b   d3
  1457.         bne.s   fx_02nocnt0
  1458.         btst    #5,msng_flags(a4)
  1459.         bne fx_xx
  1460. fx_02nocnt0 add.w   d4,trk_prevper(a5)
  1461.         move.w  trk_prevper(a5),d5
  1462.         bra.w   plr_newper
  1463. ;   **************************************** Effect 12 ******
  1464. fx_12       tst.b   d3
  1465.         bne fx_xx
  1466.         add.w   d4,trk_prevper(a5)
  1467.         move.w  trk_prevper(a5),d5
  1468.         bra plr_newper
  1469. ;   **************************************** Effect 00 ******
  1470. fx_00:      tst.b   d4  ;both fxqualifiers are 0s: no arpeggio
  1471.         beq.w   fx_xx
  1472.         move.l  d3,d0
  1473.         divu    #3,d0
  1474.         swap    d0
  1475.         tst.w   d0
  1476.         bne.s   fx_arp12
  1477.         and.b   #$0f,d4
  1478.         add.b   (a5),d4
  1479.         bra.s   fx_doarp
  1480. fx_arp12:   subq.b  #1,d0
  1481.         bne.s   fx_arp2
  1482.         lsr.b   #4,d4
  1483.         add.b   (a5),d4
  1484.         bra.s   fx_doarp
  1485. fx_arp2:    move.b  (a5),d4
  1486. fx_doarp:   subq.b  #1,d4       ;-1 to make it 0 - 127
  1487.         add.b   msng_playtransp(a4),d4  ;add play transpose
  1488.         add.b   trk_stransp(a5),d4  ;add instrument transpose
  1489.         add.b   d4,d4
  1490.         movea.l trk_periodtbl(a5),a1
  1491.         move.w  0(a1,d4.w),d5
  1492.         bra.w   plr_newtmp
  1493. ;   **************************************** Effect 04 ******
  1494. fx_14       move.b  #6,trk_vibshift(a5)
  1495.         bra.s   vib_cont
  1496. fx_04       move.b  #5,trk_vibshift(a5)
  1497. vib_cont    tst.b   d3
  1498.         bne.s   nonvib
  1499.         move.b  d4,d1
  1500.         beq.s   nonvib
  1501.         and.w   #$0f,d1
  1502.         beq.s   plr_chgvibspd
  1503.         move.w  d1,trk_vibrsz(a5)
  1504. plr_chgvibspd:  and.b   #$f0,d4
  1505.         beq.s   nonvib
  1506.         lsr.b   #3,d4
  1507.         and.b   #$3e,d4
  1508.         move.b  d4,trk_vibrspd(a5)
  1509. nonvib:     move.b  trk_vibroffs(a5),d0
  1510.         lsr.b   #2,d0
  1511.         and.w   #$1f,d0
  1512.         moveq   #0,d1
  1513.         lea sinetable(pc),a0
  1514.         move.b  0(a0,d0.w),d5
  1515.         ext.w   d5
  1516.         muls    trk_vibrsz(a5),d5
  1517.         move.b  trk_vibshift(a5),d1
  1518.         asr.w   d1,d5
  1519.         add.w   trk_prevper(a5),d5
  1520.         move.b  trk_vibrspd(a5),d0
  1521.         add.b   d0,trk_vibroffs(a5)
  1522.         bra.w   plr_newtmp
  1523. ;   **************************************** Effect 06 ******
  1524. fx_06:      tst.b   d3
  1525.         bne.s   fx_06nocnt0
  1526.         btst    #5,msng_flags(a4)
  1527.         bne fx_xx
  1528. fx_06nocnt0 bsr.s   plr_volslide        ;Volume slide
  1529.         bra.s   nonvib          ;+ Vibrato
  1530. ;   **************************************** Effect 07 ******
  1531. fx_07       tst.b   d3
  1532.         bne.s   nontre
  1533.         move.b  d4,d1
  1534.         beq.s   nontre
  1535.         and.w   #$0f,d1
  1536.         beq.s   plr_chgtrespd
  1537.         move.w  d1,trk_tremsz(a5)
  1538. plr_chgtrespd   and.b   #$f0,d4
  1539.         beq.s   nonvib
  1540.         lsr.b   #2,d4
  1541.         and.b   #$3e,d4
  1542.         move.b  d4,trk_tremspd(a5)
  1543. nontre      move.b  trk_tremoffs(a5),d0
  1544.         lsr.b   #3,d0
  1545.         and.w   #$1f,d0
  1546.         moveq   #0,d1
  1547.         lea sinetable(pc),a0
  1548.         move.b  0(a0,d0.w),d5
  1549.         ext.w   d5
  1550.         muls    trk_tremsz(a5),d5
  1551.         asr.w   #7,d5
  1552.         move.b  trk_tremspd(a5),d0
  1553.         add.b   d0,trk_tremoffs(a5)
  1554.         move.b  trk_prevvol(a5),d1
  1555.         add.b   d5,d1
  1556.         bpl.s   tre_pos
  1557.         moveq   #0,d1
  1558. tre_pos     cmp.b   #64,d1
  1559.         ble.s   tre_no2hi
  1560.         moveq   #64,d1
  1561. tre_no2hi   move.b  d1,trk_tempvol(a5)
  1562.         bra.w   fx_xx
  1563. ;   **************************************** Effect 0D/0A ***
  1564. fx_0a:
  1565. fx_0d:      tst.b   d3
  1566.         bne.s   fx_0dnocnt0
  1567.         btst    #5,msng_flags(a4)
  1568.         bne fx_xx
  1569. fx_0dnocnt0 bsr.s   plr_volslide
  1570.         bra fx_xx
  1571. ;   ********* VOLUME SLIDE FUNCTION *************************
  1572. plr_volslide    move.b  d4,d0
  1573.         moveq   #0,d1
  1574.         move.b  trk_prevvol(a5),d1 ;move previous vol to d1
  1575.         and.b   #$f0,d0
  1576.         bne.s   crescendo
  1577.         sub.b   d4,d1   ;sub from prev. vol
  1578. voltest0    bpl.s   novolover64
  1579.         moveq   #0,d1   ;volumes under zero not accepted!!!
  1580.         bra.s   novolover64
  1581. crescendo:  lsr.b   #4,d0
  1582.         add.b   d0,d1
  1583. voltest     cmp.b   #64,d1
  1584.         ble.s   novolover64
  1585.         moveq   #64,d1
  1586. novolover64 move.b  d1,trk_prevvol(a5)
  1587.         rts
  1588. ;   **************************************** Effect 1A ******
  1589. fx_1a       tst.b   d3
  1590.         bne fx_xx
  1591.         move.b  trk_prevvol(a5),d1
  1592.         add.b   d4,d1
  1593.         bsr.s   voltest
  1594.         bra fx_xx
  1595. ;   **************************************** Effect 1B ******
  1596. fx_1b       tst.b   d3
  1597.         bne fx_xx
  1598.         move.b  trk_prevvol(a5),d1
  1599.         sub.b   d4,d1
  1600.         bsr.s   voltest0
  1601.         bra fx_xx
  1602. ;   **************************************** Effect 05 ******
  1603. fx_05:      tst.b   d3
  1604.         bne.s   fx_05nocnt0
  1605.         btst    #5,msng_flags(a4)
  1606.         bne fx_xx
  1607. fx_05nocnt0 bsr.s   plr_volslide        ;Volume slide
  1608.         bra.s   fx_03nocnt0
  1609. ;   **************************************** Effect 03 ******
  1610. fx_03:      tst.b   d3
  1611.         bne.s   fx_03nocnt0
  1612.         btst    #5,msng_flags(a4)
  1613.         bne fx_xx
  1614. fx_03nocnt0 move.w  trk_porttrgper(a5),d0   ;d0 = target period
  1615.         beq.w   fx_xx   ;no target period specified
  1616.         move.w  trk_prevper(a5),d1  ;d1 = curr. period
  1617.         move.b  trk_prevportspd(a5),d4  ;get prev. speed
  1618.         cmp.w   d0,d1
  1619.         bhi.s   subper  ;curr. period > target period
  1620.         add.w   d4,d1   ;add the period
  1621.         cmp.w   d0,d1
  1622.         bge.s   targreached
  1623.         bra.s   targnreach
  1624. subper:     sub.w   d4,d1   ;subtract
  1625.         cmp.w   d0,d1   ;compare current period to target period
  1626.         bgt.s   targnreach
  1627. targreached:    move.w  trk_porttrgper(a5),d1 ;eventually push target period
  1628.         clr.w   trk_porttrgper(a5) ;now we can forget everything
  1629. targnreach: move.w  d1,trk_prevper(a5)
  1630.         move.w  d1,d5
  1631.         bra.s   plr_newper
  1632. ;   **************************************** Effect 13 ******
  1633. fx_13:      move.w  trk_prevper(a5),d5 ;this is very simple: get the old period
  1634.         cmp.b   #3,d3       ;and..
  1635.         bge.s   plr_newper  ;if counter < 3
  1636.         sub.w   d4,d5   ;subtract effect qualifier
  1637.         bra.s   plr_newper
  1638. ;   **************************************** Effect 10 ******
  1639. fx_10:
  1640.     IFNE    MIDI
  1641.         tst.b   d3
  1642.         bne.s   fx_xx
  1643.         move.w  d4,d0
  1644.         bsr.w   _InitMIDIDump
  1645.     ENDC
  1646.         bra.s   fx_xx
  1647. ;   **************************************** Effect 1E ******
  1648. fx_1e       tst.w   blkdelay-DB(a6)
  1649.         bne.s   fx_xx
  1650.         addq.w  #1,d4
  1651.         move.w  d4,blkdelay-DB(a6)
  1652.         bra.s   fx_xx
  1653. ;   **************************************** Effect 18 ******
  1654. fx_18       cmp.b   d4,d3
  1655.         bne.s   fx_xx
  1656.         clr.b   trk_prevvol(a5)
  1657.         bra.s   fx_xx
  1658. ;   **************************************** Effect 1F ******
  1659. fx_1f       move.b  d4,d1
  1660.         lsr.b   #4,d4       ;note delay
  1661.         beq.s   nonotedelay
  1662.         cmp.b   d4,d3       ;compare to counter
  1663.         blt.s   fx_xx       ;tick not reached
  1664.         bne.s   nonotedelay
  1665.         bsr playfxnote  ;trigger note
  1666. nonotedelay and.w   #$0f,d1     ;retrig?
  1667.         beq.s   fx_xx
  1668.         moveq   #0,d0
  1669.         move.b  d3,d0
  1670.         divu    d1,d0
  1671.         swap    d0      ;get modulo of counter/tick
  1672.         tst.w   d0
  1673.         bne.s   fx_xx
  1674.         bsr playfxnote  ;retrigger
  1675.         bra.s   fx_xx
  1676. ;   **************************************** Effect 0F ******
  1677. fx_0f       bsr cmd_F
  1678. ;   *********************************************************
  1679. plr_newper
  1680. fx_xx
  1681.     IFNE    SYNTH
  1682.         move.l  trk_synthptr(a5),d0
  1683.         beq.s   plr_nosynth
  1684.         bsr.w   synth_start
  1685.         bra.s   plr_tmpper
  1686. plr_newtmp  move.l  trk_synthptr(a5),d0
  1687.         beq.s   plr_tmpper
  1688.         bsr.w   synth_start2
  1689.         bra.s   plr_tmpper
  1690.     ENDC
  1691. plr_nosynth move.w  trk_prevper(a5),d5
  1692.     IFEQ    SYNTH
  1693. plr_newtmp
  1694.     ENDC
  1695. plr_tmpper  movea.l trk_audioaddr(a5),a1    ;get channel address
  1696.         move.w  d5,ac_per(a1)       ;push period
  1697.         beq.s   endl
  1698.         move.b  trk_tempvol(a5),d0
  1699.         bmi.s   plr_notmpvol
  1700.         move.b  d0,ac_vol+1(a1)
  1701.         st  trk_tempvol(a5)
  1702.         bra.s   endl
  1703. plr_notmpvol    move.b  trk_prevvol(a5),ac_vol+1(a1)    ;get volume & push it
  1704. endl:       addq.b  #1,d7           ;increment channel number
  1705.         cmp.w   numtracks-DB(a6),d7 ;all channels done???
  1706.         blt.w   plr_loop1       ;not yet!!!
  1707. plr_endfx:  ;turn on DMA
  1708.         move.w  dmaonmsk-DB(a6),d0  ;dmaonmsk contains the mask of
  1709.     IFNE    MIDI
  1710.         beq.s   sdma_nodmaon    ;the channels that must be turned on
  1711.     ENDC
  1712.     IFEQ    MIDI
  1713.         beq.s   plr_exit
  1714.     ENDC    
  1715.         bset    #15,d0  ;DMAF_SETCLR: set these bits in dmacon
  1716.         moveq   #80,d1
  1717. ; The following line makes the playroutine one scanline slower. If your
  1718. ; song works well without the following instruction, you can leave it out.
  1719.     IFNE    SYNTH
  1720.         add.w   d1,d1   ;sometimes double wait time is required
  1721.     ENDC
  1722.         bsr.s   _Wait1line
  1723.         move.w  d0,$dff096  ;do that!!!
  1724.         moveq   #80,d1
  1725.         bsr.s   _Wait1line
  1726.         lea trackdataptrs-DB(a6),a1
  1727.         bsr.s   pushnewvals
  1728.         bsr.s   pushnewvals
  1729.         bsr.s   pushnewvals
  1730.         bsr.s   pushnewvals
  1731.     IFNE    MIDI
  1732. sdma_nodmaon    lea bytesinnotebuff-DB(a6),a0
  1733.         move.w  (a0)+,d0
  1734.         beq.s   plr_exit
  1735.         bsr.w   _AddMIDId
  1736.     ENDC
  1737. plr_exit:   movem.l (sp)+,d2-d7/a2-a6
  1738.         moveq   #1,d0
  1739.         rts
  1740.  
  1741. _Wait1line: move.w  d0,-(sp)    ;d1 = vsync counters to wait - 1
  1742. wl0:        move.b  $dff007,d0
  1743. wl1:        cmp.b   $dff007,d0
  1744.         beq.s   wl1
  1745.         dbf d1,wl0
  1746.         move.w  (sp)+,d0
  1747.         rts
  1748. pushnewvals:    movea.l (a1)+,a5
  1749.         lsr.b   #1,d0
  1750.         bcc.s   rpnewv
  1751.         move.l  trk_sampleptr(a5),d1
  1752.         beq.s   rpnewv
  1753.         movea.l trk_audioaddr(a5),a0
  1754.         move.l  d1,ac_ptr(a0)
  1755.         move.w  trk_samplelen(a5),ac_len(a0)
  1756. rpnewv:     rts
  1757.  
  1758. cmd_F       cmp.b   #$f1,d4
  1759.         bne.s   no0ff1
  1760.         cmp.b   #3,d3
  1761.         beq.s   playfxnote
  1762.         rts
  1763. no0ff1:     cmp.b   #$f2,d4
  1764.         bne.s   no0ff2
  1765.         cmp.b   #3,d3
  1766.         beq.s   playfxnote
  1767.         rts
  1768. no0ff2:     cmp.b   #$f3,d4
  1769.         bne.s   no0ff3
  1770.         move.b  d3,d0
  1771.         beq.s   cF_rts
  1772.         and.b   #1,d0       ;is 2 or 4
  1773.         bne.s   cF_rts
  1774. playfxnote: moveq   #0,d1
  1775.         move.b  (a5),d1     ;get note # of previous note
  1776.         beq.s   cF_rts
  1777.         move.b  trk_noteoffcnt(a5),d0   ;get hold counter
  1778.         bmi.s   pfxn_nohold     ;no hold, or hold over
  1779.         add.b   d3,d0           ;increase by counter val
  1780.         bra.s   pfxn_hold
  1781. pfxn_nohold move.b  trk_inithold(a5),d0 ;get initial hold
  1782.         bne.s   pfxn_hold
  1783.         st  d0
  1784. pfxn_hold   move.b  d0,trk_noteoffcnt(a5)
  1785.         movem.l d3/a3,-(sp)
  1786.         moveq   #0,d3
  1787.         move.b  trk_previnstr(a5),d3    ;and prev. sample #
  1788.         movea.l trk_previnstra(a5),a3
  1789.         bsr _PlayNote
  1790.         movem.l (sp)+,d3/a3
  1791. cF_rts      rts
  1792. no0ff3:     cmp.b   #$f4,d4     ;triplet cmd 1
  1793.         bne.s   no0ff4
  1794.         moveq   #0,d0
  1795.         move.b  msng_tempo2(a4),d0
  1796.         divu    #3,d0
  1797.         cmp.b   d0,d3
  1798.         beq.s   playfxnote
  1799.         rts
  1800. no0ff4      cmp.b   #$f5,d4     ;triplet cmd 2
  1801.         bne.s   no0ff5
  1802.         moveq   #0,d0
  1803.         move.b  msng_tempo2(a4),d0
  1804.         divu    #3,d0
  1805.         add.w   d0,d0
  1806.         cmp.b   d0,d3
  1807.         beq.s   playfxnote
  1808.         rts
  1809. no0ff5      cmp.b   #$f8,d4     ;f8 = filter off
  1810.         beq.s   plr_filteroff
  1811.         cmp.b   #$f9,d4     ;f9 = filter on
  1812.         bne.s   cF_rts
  1813.         bclr    #1,$bfe001
  1814.         rts
  1815. plr_filteroff:  bset    #1,$bfe001
  1816.         rts
  1817.  
  1818. _SetTempo:
  1819.     IFNE    CIAB
  1820.         move.l  _module-DB(a6),d1
  1821.         beq.s   ST_x
  1822.         move.l  d1,a0
  1823.         movea.l mmd_songinfo(a0),a0
  1824.         btst    #5,msng_flags2(a0)
  1825.         bne.s   ST_bpm
  1826.         cmp.w   #10,d0  ;If tempo <= 10, use SoundTracker tempo
  1827.         bhi.s   calctempo
  1828.         subq.b  #1,d0
  1829.         add.w   d0,d0
  1830.         move.w  sttempo+2(pc,d0.w),d1
  1831.         bra.s   pushtempo
  1832. calctempo:  move.l  timerdiv-DB(a6),d1
  1833.         divu    d0,d1
  1834. pushtempo:  movea.l craddr+4-DB(a6),a0
  1835.         move.b  d1,(a0)     ;and set the CIA timer
  1836.         lsr.w   #8,d1
  1837.         movea.l craddr+8-DB(a6),a0
  1838.         move.b  d1,(a0)
  1839.     ENDC
  1840. ST_x        rts ;   vv-- These values are the SoundTracker tempos (approx.)
  1841. sttempo:    dc.w    $0f00
  1842.     IFNE    CIAB
  1843.         dc.w    2417,4833,7250,9666,12083,14500,16916,19332,21436,24163
  1844. ST_bpm      move.b  msng_flags2(a0),d1
  1845.         and.w   #$1F,d1
  1846.         addq.b  #1,d1
  1847.         mulu    d1,d0
  1848.         move.l  bpmdiv-DB(a6),d1
  1849.         divu    d0,d1
  1850.         bra.s   pushtempo
  1851.     ENDC
  1852.  
  1853.     IFNE    MIDI
  1854. midicmds
  1855.     IFNE    HOLD
  1856.         tst.b   trk_noteoffcnt(a5)
  1857.         bmi.s   midi_nowaitoff
  1858.         subq.b  #1,trk_noteoffcnt(a5)
  1859.         bpl.s   midi_nowaitoff
  1860.         move.l  a5,a1
  1861.         move.b  trk_prevmidin(a5),d1
  1862.         beq.s   midi_nowaitoff  ;no note
  1863.         lea noteondata-DB(a6),a0
  1864.         bsr.w   choff_midi
  1865. midi_nowaitoff:
  1866.     ENDC
  1867.         add.b   d6,d6   ;* 2
  1868.         move.w  midicmd_table(pc,d6.w),d0
  1869.         jmp midifx(pc,d0.w)
  1870. midicmd_table:  dc.w    mfx_00-midifx,mfx_01-midifx,mfx_02-midifx,mfx_03-midifx,mfx_04-midifx
  1871.         dc.w    mfx_05-midifx,endl-midifx,endl-midifx,endl-midifx,endl-midifx
  1872.         dc.w    mfx_0a-midifx,endl-midifx,endl-midifx,mfx_0d-midifx,mfx_0e-midifx
  1873.         dc.w    mfx_0f-midifx
  1874.         dc.w    mfx_10-midifx,endl-midifx,endl-midifx,mfx_13-midifx
  1875.         dc.w    endl-midifx,endl-midifx,endl-midifx,mfx_17-midifx
  1876.         dc.w    endl-midifx,endl-midifx,endl-midifx,endl-midifx
  1877.         dc.w    endl-midifx,endl-midifx,endl-midifx,mfx_1f-midifx
  1878. midifx      
  1879. mfx_01      lea prevmidipbend-DB(a6),a0
  1880.         moveq   #0,d1
  1881.         move.b  trk_prevmidich(a5),d1   ;get previous midi channel
  1882.         add.b   d1,d1       ;UWORD index
  1883.         tst.b   d4      ;x100??
  1884.         beq.s   resetpbend
  1885.         move.w  0(a0,d1.w),d0   ;get previous pitch bend
  1886.         lsl.w   #3,d4       ;multiply bend value by 8
  1887.         add.w   d4,d0
  1888.         cmp.w   #$3fff,d0
  1889.         bls.s   bendpitch
  1890.         move.w  #$3fff,d0
  1891. bendpitch:  move.w  d0,0(a0,d1.w)   ;save current pitch bend
  1892.         lsr.b   #1,d1       ;back to UBYTE
  1893.         or.b    #$e0,d1
  1894.         lea noteondata-DB(a6),a0
  1895.         move.b  d1,(a0)     ;midi command & channel
  1896.         move.b  d0,1(a0)    ;lower value
  1897.         and.b   #$7f,1(a0)  ;clear bit 7
  1898.         lsr.w   #7,d0
  1899.         and.b   #$7f,d0     ;clr bit 7
  1900.         move.b  d0,2(a0)    ;higher 7 bits
  1901.         moveq   #3,d0
  1902.         bsr.w   _AddMIDId
  1903.         bra.w   endl
  1904.  
  1905. mfx_02      lea prevmidipbend-DB(a6),a0
  1906.         moveq   #0,d1
  1907.         move.b  trk_prevmidich(a5),d1
  1908.         add.b   d1,d1
  1909.         tst.b   d4
  1910.         beq.s   resetpbend  ;x200??
  1911.         move.w  0(a0,d1.w),d0
  1912.         lsl.w   #3,d4
  1913.         sub.w   d4,d0
  1914.         bpl.s   bendpitch   ;not under 0
  1915.         moveq   #0,d0
  1916.         bra.s   bendpitch
  1917. resetpbend: tst.b   d3      ;d3 = counter (remember??)
  1918.         bne.w   endl
  1919.         move.w  #$2000,d0
  1920.         bra.s   bendpitch
  1921. mfx_13
  1922. mfx_03      tst.b   d3
  1923.         bne.w   endl
  1924.         lea prevmidipbend-DB(a6),a0
  1925.         moveq   #0,d1
  1926.         move.b  trk_prevmidich(a5),d1
  1927.         add.b   d1,d1
  1928.         move.b  d4,d0
  1929.         add.b   #128,d0
  1930.         lsl.w   #6,d0
  1931.         bra.s   bendpitch
  1932.  
  1933. mfx_0d      tst.b   d3
  1934.         bne.w   endl
  1935.         lea noteondata+1-DB(a6),a0  ;CHANNEL AFTERTOUCH
  1936.         move.b  d4,(a0) ;value
  1937.         bmi.w   endl
  1938.         move.b  trk_prevmidich(a5),-(a0)
  1939.         or.b    #$d0,(a0)
  1940.         moveq   #2,d0
  1941.         bsr.w   _AddMIDId
  1942.         bra.w   endl
  1943.  
  1944. mfx_0a      tst.b   d3
  1945.         bne.w   endl
  1946.         lea noteondata+2-DB(a6),a0  ;POLYPHONIC AFTERTOUCH
  1947.         and.b   #$7f,d4
  1948.         move.b  d4,(a0)
  1949.         move.b  trk_prevmidin(a5),-(a0)
  1950.         ble.w   endl
  1951.         move.b  trk_prevmidich(a5),-(a0)
  1952.         or.b    #$A0,(a0)
  1953.         moveq   #3,d0
  1954.         bsr.w   _AddMIDId
  1955.         bra.w   endl
  1956.  
  1957. mfx_17      moveq   #$07,d0     ;07 = VOLUME
  1958.         bra.s   pushctrldata
  1959.  
  1960. mfx_04      moveq   #$01,d0     ;01 = MODULATION WHEEL
  1961.         bra.s   pushctrldata
  1962.  
  1963. mfx_0e      moveq   #$0a,d0
  1964. pushctrldata    tst.b   d3      ;do it only once in a note
  1965.         bne.w   endl        ;(when counter = 0)
  1966.         lea noteondata+2-DB(a6),a0 ;push "control change" data,
  1967.         move.b  d4,(a0)     ;second databyte
  1968.         bmi.w   endl        ;$0 - $7F only
  1969.         move.b  d0,-(a0)    ;1st databyte
  1970.         move.b  trk_prevmidich(a5),-(a0)    ;MIDI channel
  1971.         or.b    #$b0,(a0)   ;command (B)
  1972.         moveq   #3,d0
  1973.         bsr.w   _AddMIDId
  1974.         bra.w   endl
  1975.  
  1976. mfx_05      and.b   #$7f,d4     ;set contr. value of curr. MIDI ch.
  1977.         move.b  trk_prevmidich(a5),d6
  1978.         lea midicontrnum-DB(a6),a0
  1979.         adda.w  d6,a0
  1980.         move.b  d4,(a0)
  1981.         bra.w   endl
  1982.  
  1983. mfx_0f      cmp.b   #$fa,d4     ;hold pedal ON
  1984.         bne.s   nomffa
  1985.         moveq   #$40,d0
  1986.         moveq   #$7f,d4
  1987.         bra.s   pushctrldata
  1988. nomffa      cmp.b   #$fb,d4     ;hold pedal OFF
  1989.         bne.s   mfx_0f_2
  1990.         moveq   #$40,d0
  1991.         moveq   #$00,d4
  1992.         bra.s   pushctrldata
  1993. mfx_0f_2    bsr.w   cmd_F
  1994.         bra.w   endl
  1995.  
  1996. mfx_00      tst.b   d4
  1997.         beq.w   endl
  1998.         and.b   #$7f,d4
  1999.         move.b  trk_prevmidich(a5),d6
  2000.         lea midicontrnum-DB(a6),a0
  2001.         move.b  0(a0,d6.w),d0
  2002.         bra.s   pushctrldata
  2003.  
  2004. mfx_10      tst.b   d3
  2005.         bne.w   endl
  2006.         move.w  d4,d0
  2007.         bsr.w   _InitMIDIDump
  2008.         bra.w   endl
  2009.  
  2010. mfx_1f      move.b  d4,d1
  2011.         lsr.b   #4,d4       ;note delay
  2012.         beq.s   nonotedelay_m
  2013.         cmp.b   d4,d3       ;compare to counter
  2014.         blt endl        ;tick not reached
  2015.         bne.s   nonotedelay_m
  2016.         bsr playfxnote  ;trigger note
  2017. nonotedelay_m   and.w   #$0f,d1     ;retrig?
  2018.         beq endl
  2019.         moveq   #0,d0
  2020.         move.b  d3,d0
  2021.         divu    d1,d0
  2022.         swap    d0      ;get modulo of counter/tick
  2023.         tst.w   d0
  2024.         bne endl
  2025.         bsr playfxnote  ;retrigger
  2026.         bra endl
  2027.  
  2028. _ResetMIDI: movem.l d2/a2/a6,-(sp)
  2029.         movea.l 4.w,a6      ;ExecBase
  2030.         jsr -$78(a6)    ;Disable()
  2031.         lea DB,a6
  2032. ; Clear preset memory
  2033.         lea prevmidicpres-DB(a6),a0
  2034.         moveq   #7,d2
  2035. RM_loop0    clr.l   (a0)+   ;force presets to be set again
  2036.         dbf d2,RM_loop0
  2037.         clr.b   lastcmdbyte
  2038. ; Reset pitchbenders & modulation wheels
  2039.         lea midiresd-DB(a6),a2
  2040.         move.b  #$e0,(a2)
  2041.         move.b  #$b0,3(a2)
  2042.         moveq   #15,d2
  2043. respbendl:  movea.l a2,a0
  2044.         moveq   #6,d0
  2045.         bsr.w   _AddMIDId
  2046.         addq.b  #1,(a2)
  2047.         addq.b  #1,3(a2)
  2048.         dbf d2,respbendl
  2049.         lea prevmidipbend-DB(a6),a2
  2050.         moveq   #15,d2
  2051. resprevpbends:  move.w  #$2000,(a2)+
  2052.         dbf d2,resprevpbends
  2053. ; Clear dump variables
  2054.         clr.b   sysx-DB(a6)
  2055.         lea dumpqueue-DB(a6),a0
  2056.         move.l  a0,dqreadptr-DB(a6)
  2057.         move.l  a0,dqwriteptr-DB(a6)
  2058.         clr.w   dqentries-DB(a6)
  2059. ; Enable & exit
  2060.         movea.l 4.w,a6
  2061.         jsr -$7e(a6)    ;Enable()
  2062.         movem.l (sp)+,d2/a2/a6
  2063.         rts
  2064.     ENDC
  2065.  
  2066. ; *************************************************************************
  2067. ; *************************************************************************
  2068. ; ***********          P U B L I C   F U N C T I O N S          ***********
  2069. ; *************************************************************************
  2070. ; *************************************************************************
  2071.  
  2072.     IFEQ    EASY
  2073.         XDEF    _InitModule,_PlayModule
  2074.         XDEF    _InitPlayer,_RemPlayer,_StopPlayer
  2075.         XDEF    _ContModule
  2076.     ENDC
  2077.  
  2078. ; *************************************************************************
  2079. ; InitModule(a0 = module) -- extract expansion data etc.. from V3.xx module
  2080. ; *************************************************************************
  2081.  
  2082. _InitModule:    movem.l a2-a3/d2,-(sp)
  2083.         move.l  a0,-(sp)
  2084.         beq IM_exit         ;0 => xit
  2085.     IFNE    RELVOL
  2086.         movea.l mmd_songinfo(a0),a1 ;MMD0song
  2087.         move.b  msng_mastervol(a1),d0   ;d0 = mastervol
  2088.         ext.w   d0
  2089.         lea trackdataptrs,a2
  2090.         cmp.b   #'2',3(a0)      ;MMD2?
  2091.         bne.s   IM_mmd01
  2092.         move.w  msng_numtracks(a1),d1
  2093.         subq.w  #1,d1
  2094.         movea.l msng_trkvoltbl(a1),a1
  2095.         bra.s   IM_loop0
  2096. IM_mmd01    lea msng_trkvol(a1),a1  ;a1 = trkvol
  2097.         moveq   #MAX_MMD1_TRACKS-1,d1
  2098. IM_loop0    move.b  (a1)+,d2    ;get vol...
  2099.         ext.w   d2
  2100.         move.l  (a2)+,a3    ;pointer to track data
  2101.         mulu    d0,d2       ;mastervol * trackvol
  2102.         lsr.w   #4,d2
  2103.         move.w  d2,trk_trackvol(a3)
  2104.         dbf d1,IM_loop0
  2105.     ENDC
  2106.     IFNE    SYNTH
  2107.         lea trackdataptrs,a2
  2108.         moveq   #3,d1
  2109. IM_loop1    move.l  (a2)+,a3
  2110.         clr.l   trk_synthptr(a3)
  2111.         clr.b   trk_synthtype(a3)
  2112.         dbf d1,IM_loop1
  2113.     ENDC
  2114.         lea holdvals,a2
  2115.         movea.l a0,a3
  2116.         move.l  mmd_expdata(a0),d0  ;expdata...
  2117.     IFEQ    MIDI
  2118.         beq.s   IM_clrhlddec        ;none here
  2119.     ENDC
  2120.     IFNE    MIDI
  2121.         beq.w   IM_clrhlddec
  2122.     ENDC
  2123.         move.l  d0,a1
  2124.         move.l  4(a1),d0        ;exp_smp
  2125.     IFEQ    MIDI
  2126.         beq.s   IM_clrhlddec    ;again.. nothing
  2127.     ENDC
  2128.     IFNE    MIDI
  2129.         beq.w   IM_clrhlddec
  2130.     ENDC
  2131.         move.l  d0,a0       ;InstrExt...
  2132.         move.w  8(a1),d2    ;# of entries
  2133.     IFEQ    MIDI
  2134.         beq.s   IM_clrhlddec
  2135.     ENDC
  2136.     IFNE    MIDI
  2137.         beq.w   IM_clrhlddec
  2138.     ENDC
  2139.         subq.w  #1,d2       ;-1 (for dbf)
  2140.         move.w  10(a1),d0   ;entry size
  2141.         movea.l mmd_songinfo(a3),a3 ;MMD0song
  2142.     IFNE    MIDI
  2143.         lea 4*63(a2),a1 ;pointer to ext_midipsets...
  2144.     ENDC
  2145. IM_loop2    clr.b   126(a2)     ;clear finetune
  2146.         cmp.w   #3,d0
  2147.         ble.s   IM_noftune
  2148.         move.b  3(a0),126(a2)   ;InstrExt.finetune -> finetune
  2149. IM_noftune  clr.b   189(a2)     ;clear flags
  2150.         cmp.w   #6,d0
  2151.         blt.s   IM_noflags
  2152.         move.b  5(a0),189(a2)   ;InstrExt.flags -> flags
  2153.         bra.s   IM_gotflags
  2154. IM_noflags  cmp.w   #1,inst_replen(a3)
  2155.         bls.s   IM_gotflags
  2156.         bset    #0,189(a2)
  2157. IM_gotflags
  2158.     IFNE    MIDI
  2159.         cmp.w   #2,d0
  2160.         ble.s   IM_nsmnoff
  2161.         tst.b   2(a0)       ;suppress MIDI note off?
  2162.         beq.s   IM_nsmnoff
  2163.         bset    #7,inst_midich(a3)
  2164. IM_nsmnoff  move.b  inst_midipreset(a3),d1
  2165.         ext.w   d1
  2166.         move.w  d1,(a1)
  2167.         cmp.w   #8,d0
  2168.         ble.s   IM_nolongpset
  2169.         move.w  6(a0),(a1)  ;-> ext_midipsets
  2170.         btst    #1,5(a0)
  2171.         beq.s   IM_nolongpset
  2172.         bset    #6,inst_midich(a3)
  2173. IM_nolongpset   addq.l  #2,a1
  2174.     ENDC
  2175.         move.b  1(a0),63(a2)    ;InstrExt.decay -> decay
  2176.         move.b  (a0),(a2)+  ;InstrExt.hold -> holdvals
  2177.         adda.w  d0,a0       ;ptr to next InstrExt
  2178.         addq.l  #8,a3       ;next instrument...
  2179.         dbf d2,IM_loop2
  2180.         bra.s   IM_exit
  2181. IM_clrhlddec    move.w  #3*63-1,d0  ;no InstrExt => clear holdvals/decays
  2182. IM_loop3    clr.w   (a2)+       ;..and finetunes/flags/ext_psets
  2183.         dbf d0,IM_loop3
  2184.         movea.l (sp),a0
  2185. ; -------- For (very old) MMDs, with no InstrExt, set flags/SSFLG_LOOP,
  2186. ; -------- also copy inst_midipreset to ext_midipsets.
  2187.         movea.l mmd_songinfo(a0),a3
  2188.         lea flags,a2
  2189.     IFNE    MIDI
  2190.         lea ext_midipsets,a1
  2191.     ENDC
  2192.         moveq   #62,d0
  2193. IM_loop4    cmp.w   #1,inst_replen(a3)
  2194.         bls.s   IM_noreptflg
  2195.         bset    #0,(a2)
  2196. IM_noreptflg    addq.l  #1,a2
  2197.     IFNE    MIDI
  2198.         move.b  inst_midipreset(a3),d1
  2199.         ext.w   d1
  2200.         move.w  d1,(a1)+
  2201.     ENDC
  2202.         addq.l  #8,a3       ;next inst
  2203.         dbf d0,IM_loop4
  2204. IM_exit     addq.l  #4,sp
  2205.         movem.l (sp)+,a2-a3/d2
  2206.         rts
  2207. ; *************************************************************************
  2208. ; InitPlayer() -- allocate interrupt, audio, serial port etc...
  2209. ; *************************************************************************
  2210. _InitPlayer:
  2211.     IFNE    MIDI
  2212.         bsr.w   _GetSerial
  2213.         tst.l   d0
  2214.         bne.s   IP_error
  2215.     ENDC
  2216.         bsr.w   _AudioInit
  2217.         tst.l   d0
  2218.         bne.s   IP_error
  2219.         rts
  2220. IP_error    bsr.s   _RemPlayer
  2221.         moveq   #-1,d0
  2222.         rts
  2223. ; *************************************************************************
  2224. ; RemPlayer() -- free interrupt, audio, serial port etc..
  2225. ; *************************************************************************
  2226. _RemPlayer: move.b  _timeropen,d0
  2227.         beq.s   RP_notimer  ;timer is not ours
  2228.         bsr.s   _StopPlayer
  2229. RP_notimer: bsr.w   _AudioRem
  2230.     IFNE    MIDI
  2231.         bra.w   _FreeSerial
  2232.     ELSEIF
  2233.         rts
  2234.     ENDC
  2235. ; *************************************************************************
  2236. ; StopPlayer() -- stop the music
  2237. ; *************************************************************************
  2238. _StopPlayer:    lea DB,a1
  2239.         move.b  _timeropen-DB(a1),d0
  2240.         beq.s   SP_end      ;res. alloc fail.
  2241.     IFNE    CIAB
  2242.         movea.l craddr-DB(a1),a0
  2243.         bclr    #0,(a0)     ;stop timer
  2244.     ENDC
  2245.         move.l  _module-DB(a1),d0
  2246.         beq.s   SP_nomod
  2247.         move.l  d0,a0
  2248.         clr.w   mmd_pstate(a0)
  2249.         clr.l   _module-DB(a1)
  2250. SP_nomod
  2251.     IFNE    MIDI
  2252.         clr.b   lastcmdbyte-DB(a1)
  2253.     ENDC
  2254.         bra.w   SoundOff
  2255. SP_end      rts
  2256.  
  2257.  
  2258. _ContModule tst.b   _timeropen
  2259.         beq.s   SP_end
  2260.         movea.l craddr,a1
  2261.         bclr    #0,(a1)
  2262.         move.l  a0,-(sp)
  2263.         bsr.w   SoundOff
  2264.         move.l  (sp)+,a0
  2265.         moveq   #0,d0
  2266.         bra.s   contpoint
  2267. ; *************************************************************************
  2268. ; PlayModule(a0 = module)  -- initialize & play it!
  2269. ; *************************************************************************
  2270. _PlayModule:    st  d0
  2271. contpoint   movem.l a0/d0,-(sp)
  2272.         bsr _InitModule
  2273.         movem.l (sp)+,a0/d0
  2274.         move.l  a6,-(sp)
  2275.         lea DB,a6
  2276.         tst.b   _timeropen-DB(a6)
  2277.         beq PM_end      ;resource allocation failure
  2278.         move.l  a0,d1
  2279.         beq PM_end      ;module failure
  2280.     IFNE    CIAB
  2281.         movea.l craddr-DB(a6),a1
  2282.         bclr    #0,(a1)     ;stop timer...
  2283.     ENDC
  2284.         clr.l   _module-DB(a6)
  2285.     IFNE    MIDI
  2286.         clr.b   lastcmdbyte-DB(a6)
  2287.     ENDC
  2288.         move.w  _modnum,d1
  2289.         beq.s   PM_modfound
  2290. PM_nextmod  tst.l   mmd_expdata(a0)
  2291.         beq.s   PM_modfound
  2292.         move.l  mmd_expdata(a0),a1
  2293.         tst.l   (a1)
  2294.         beq.s   PM_modfound     ;no more modules here!
  2295.         move.l  (a1),a0
  2296.         subq.w  #1,d1
  2297.         bgt.s   PM_nextmod
  2298. PM_modfound cmp.b   #'T',3(a0)
  2299.         bne.s   PM_nomodT
  2300.         move.b  #'0',3(a0)  ;change MCNT to MCN0
  2301. PM_nomodT   movea.l mmd_songinfo(a0),a1     ;song
  2302.         move.b  msng_tempo2(a1),mmd_counter(a0) ;init counter
  2303.         btst    #0,msng_flags(a1)
  2304.         bne.s   PM_filon
  2305.         bset    #1,$bfe001
  2306.         bra.s   PM_filset
  2307. PM_filon    bclr    #1,$bfe001
  2308. PM_filset   tst.b   d0
  2309.         beq.s   PM_noclr
  2310.         clr.l   mmd_pline(a0)
  2311.         clr.l   rptline-DB(a6)
  2312.         clr.w   blkdelay-DB(a6)
  2313. ; ---------- Set 'pblock' and 'pseq' to correct values...
  2314. PM_noclr    cmp.b   #'2',3(a0)
  2315.         bne.s   PM_oldpbset
  2316.         move.w  mmd_psecnum(a0),d1
  2317.         move.l  a2,-(sp)        ;need extra register
  2318.         movea.l msng_sections(a1),a2
  2319.         add.w   d1,d1
  2320.         move.w  0(a2,d1.w),d1       ;get sequence number
  2321.         add.w   d1,d1
  2322.         add.w   d1,d1
  2323.         move.w  d1,mmd_pseq(a0)
  2324.         movea.l msng_pseqs(a1),a2
  2325.         movea.l 0(a2,d1.w),a2       ;PlaySeq...
  2326.         move.w  mmd_pseqnum(a0),d1
  2327.         add.w   d1,d1
  2328.         move.w  42(a2,d1.w),d1      ;and the correct block..
  2329.         move.l  (sp)+,a2
  2330.         bra.s   PM_setblk
  2331. PM_oldpbset move.w  mmd_pseqnum(a0),d1
  2332.         add.w   #msng_playseq,d1
  2333.         move.b  0(a1,d1.w),d1       ;get first playseq entry
  2334.         ext.w   d1
  2335. PM_setblk   move.w  d1,mmd_pblock(a0)
  2336.         move.w  #-1,mmd_pstate(a0)
  2337.         move.l  a0,_module-DB(a6)
  2338.         btst    #5,msng_flags2(a1)  ;BPM?
  2339.         seq bpmcounter-DB(a6)
  2340.     IFNE    CIAB
  2341.         move.w  msng_deftempo(a1),d0    ;get default tempo
  2342.         movea.l craddr-DB(a6),a1
  2343.         bsr.w   _SetTempo   ;set default tempo
  2344.         bset    #0,(a1)     ;start timer => PLAY!!
  2345.     ENDC
  2346. PM_end      move.l  (sp)+,a6
  2347.         rts
  2348. ; *************************************************************************
  2349.  
  2350. _AudioInit: movem.l a4/a6/d2-d3,-(sp)
  2351.         lea DB,a4
  2352.         moveq   #0,d2
  2353.         movea.l 4.w,a6
  2354. ;   +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ alloc signal bit
  2355.     IFNE    AUDDEV
  2356.         moveq   #1,d2
  2357.         moveq   #-1,d0
  2358.         jsr -$14a(a6)   ;AllocSignal()
  2359.         tst.b   d0
  2360.         bmi.w   initerr
  2361.         move.b  d0,sigbitnum-DB(a4)
  2362. ;   +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ prepare IORequest
  2363.         lea allocport-DB(a4),a1
  2364.         move.b  d0,15(a1)   ;set mp_SigBit
  2365.         move.l  a1,-(sp)
  2366.         suba.l  a1,a1
  2367.         jsr -$126(a6)   ;FindTask(0)
  2368.         move.l  (sp)+,a1
  2369.         move.l  d0,16(a1)   ;set mp_SigTask
  2370.         lea reqlist-DB(a4),a0
  2371.         move.l  a0,(a0)     ;NEWLIST begins...
  2372.         addq.l  #4,(a0)
  2373.         clr.l   4(a0)
  2374.         move.l  a0,8(a0)    ;NEWLIST ends...
  2375. ;   +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ open audio.device
  2376.         moveq   #2,d2
  2377.         lea allocreq-DB(a4),a1
  2378.         lea audiodevname-DB(a4),a0
  2379.         moveq   #0,d0
  2380.         moveq   #0,d1
  2381.         movea.l 4.w,a6
  2382.         jsr -$1bc(a6)   ;OpenDevice()
  2383.         tst.b   d0
  2384.         bne.w   initerr
  2385.         st  audiodevopen-DB(a4)
  2386. ;   +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ open cia resource
  2387.         moveq   #3,d2
  2388.     ENDC
  2389.     IFNE    CIAB
  2390.         cmp.b   #50,$212(a6)    ;ExecBase->VBlankFrequency
  2391.         beq.s   init_pal
  2392.         move.l  #474326,timerdiv-DB(a4) ;Assume that CIA freq is 715 909 Hz
  2393.         move.l  #3579545/2,bpmdiv-DB(a4)
  2394. init_pal    moveq   #0,d3
  2395.         lea cianame-DB(a4),a1
  2396.         move.b  #'a',3(a1)
  2397. open_ciares moveq   #0,d0
  2398.         jsr -$1f2(a6)   ;OpenResource()
  2399.         move.l  d0,_ciaresource
  2400.         beq.s   try_CIAB
  2401.         moveq   #4,d2
  2402.         move.l  d0,a6
  2403.         lea timerinterrupt-DB(a4),a1
  2404.         moveq   #0,d0       ;Timer A
  2405.         jsr -$6(a6)     ;AddICRVector()
  2406.         tst.l   d0
  2407.         beq.s   got_timer
  2408.         addq.l  #4,d3       ;add base addr index
  2409.         lea timerinterrupt-DB(a4),a1
  2410.         moveq   #1,d0       ;Timer B
  2411.         jsr -$6(a6)     ;AddICRVector()
  2412.         tst.l   d0
  2413.         beq.s   got_timer
  2414. try_CIAB    lea cianame-DB(a4),a1
  2415.         cmp.b   #'a',3(a1)
  2416.         bne.s   initerr
  2417.         addq.b  #1,3(a1)
  2418.         moveq   #8,d3       ;CIAB base addr index = 8
  2419.         bra.w   open_ciares
  2420. ;   +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ attach interrupt
  2421. got_timer   lea craddr+8-DB(a4),a6
  2422.         move.l  cia_addr(pc,d3.w),d0
  2423.         move.l  d0,(a6)
  2424.         sub.w   #$100,d0
  2425.         move.l  d0,-(a6)
  2426.         moveq   #2,d3       ;assume timer B
  2427.         btst    #9,d0       ;timer A or B ?
  2428.         bne.s   got_timerB
  2429.         subq.b  #1,d3       ;not timer B -> subtract 1
  2430.         add.w   #$100,d0    ;calc offset to timer control reg
  2431. got_timerB  add.w   #$900,d0
  2432.         move.l  d0,-(a6)
  2433.         move.l  d0,a0           ;get Control Register
  2434.         and.b   #%10000000,(a0)     ;clear CtrlReg bits 0 - 6
  2435.         move.b  d3,_timeropen-DB(a4)    ;d3: 1 = TimerA 2 = TimerB
  2436.     ENDC
  2437.     IFNE    VBLANK
  2438.         moveq   #5,d0       ;INTB_VERTB
  2439.         lea timerinterrupt-DB(a4),a1
  2440.         jsr -$a8(a6)    ;AddIntServer
  2441.         st  _timeropen-DB(a4)
  2442.     ENDC
  2443.         moveq   #0,d0
  2444. initret:    movem.l (sp)+,a4/a6/d2-d3
  2445.         rts
  2446. initerr:    move.l  d2,d0
  2447.         bra.s   initret
  2448.  
  2449. cia_addr:   dc.l    $BFE501,$BFE701,$BFD500,$BFD700
  2450.  
  2451. _AudioRem:  movem.l a5-a6,-(sp)
  2452.         lea DB,a5
  2453.         moveq   #0,d0
  2454.         move.b  _timeropen,d0
  2455.         beq.s   rem1
  2456. ;   +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ remove interrupt
  2457.         clr.b   _timeropen
  2458.     IFNE    CIAB
  2459.         move.l  _ciaresource,a6
  2460.         lea timerinterrupt-DB(a5),a1
  2461.         subq.b  #1,d0
  2462.         jsr -$c(a6)     ;RemICRVector
  2463.     ENDC
  2464.     IFNE    VBLANK
  2465.         movea.l 4.w,a6
  2466.         lea timerinterrupt(pc),a1
  2467.         moveq   #5,d0
  2468.         jsr -$ae(a6)    ;RemIntServer
  2469.     ENDC
  2470. rem1:
  2471.     IFNE    AUDDEV
  2472.         movea.l 4.w,a6
  2473.         tst.b   audiodevopen-DB(a5)
  2474.         beq.s   rem2
  2475.         move.w  #$000f,$dff096  ;stop audio DMA
  2476. ;   +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ close audio.device
  2477.         lea allocreq-DB(a5),a1
  2478.         jsr -$1c2(a6)   ;CloseDevice()
  2479.         clr.b   audiodevopen-DB(a5)
  2480. rem2:       moveq   #0,d0
  2481.         move.b  sigbitnum-DB(a5),d0
  2482.         bmi.s   rem3
  2483. ;   +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ free signal bit
  2484.         jsr -$150(a6)   ;FreeSignal()
  2485.         st  sigbitnum-DB(a5)
  2486. rem3:
  2487.     ENDC
  2488.         movem.l (sp)+,a5-a6
  2489.         rts
  2490.  
  2491.     IFNE    MIDI
  2492. _GetSerial: movem.l a5-a6,-(sp) ;Get serial port for MIDI
  2493.         lea DB,a5
  2494.         bsr.s   GetSer2
  2495.         tst.l   d0      ;got the port??
  2496.         beq.s   rgser       ;yes
  2497.         movea.l 4.w,a6      ;no..try to flush serial.device:
  2498.         jsr -$84(a6)        ;Forbid
  2499.         lea $15e(a6),a0     ;ExecBase->DeviceList
  2500.         lea serdev-DB(a5),a1    ;"serial.device"
  2501.         jsr -$114(a6)       ;FindName
  2502.         tst.l   d0
  2503.         beq.s   serdnotf        ;no serial.device!!
  2504.         move.l  d0,a1
  2505.         jsr -$1b6(a6)       ;RemDevice
  2506. serdnotf:   jsr -$8a(a6)        ;and Permit
  2507.         bsr.s   GetSer2     ;now try it again...
  2508. rgser:      movem.l (sp)+,a5-a6
  2509.         rts
  2510.  
  2511. GetSer2:    movea.l 4.w,a6
  2512.         moveq   #0,d0
  2513.         lea miscresname-DB(a5),a1
  2514.         jsr -$1f2(a6)   ;OpenResource()
  2515.         move.l  d0,miscresbase-DB(a5)
  2516.         tst.l   d0
  2517.         beq.s   gserror
  2518.         move.l  d0,a6
  2519.         lea medname-DB(a5),a1
  2520.         moveq   #0,d0       ;serial port
  2521.         jsr -$6(a6)     ;AllocMiscResource()
  2522.         tst.l   d0
  2523.         bne.s   gserror
  2524.         lea medname-DB(a5),a1
  2525.         moveq   #1,d0       ;serial bits
  2526.         jsr -$6(a6)
  2527.         tst.l   d0
  2528.         beq.s   gs2_allocok
  2529.         moveq   #0,d0
  2530.         jsr -$c(a6)     ;bits failed -> Free serial port
  2531.         bra.s   gserror
  2532. gs2_allocok move.w  $dff01c,d0
  2533.         btst    #0,d0
  2534.         sne intrson-DB(a5)
  2535.         moveq   #0,d0       ;TBE
  2536.         lea serinterrupt-DB(a5),a1
  2537.         move.l  4.w,a6
  2538.         jsr -$a2(a6)    ;SetIntVector()
  2539.         move.l  d0,prevtbe-DB(a5)
  2540.         move.w  #$8001,$dff09a  ;TBE on
  2541.         move.w  #114,$dff032    ;set baud rate (SERPER)
  2542.         st  serportalloc-DB(a5)
  2543.         moveq   #0,d0
  2544.         rts
  2545. gserror:    moveq   #-1,d0
  2546.         rts
  2547.  
  2548. _FreeSerial:    movem.l a5-a6,-(sp)
  2549.         lea DB,a5
  2550.         tst.l   miscresbase-DB(a5)
  2551.         beq.s   retfs
  2552.         tst.b   serportalloc-DB(a5)
  2553.         beq.s   retfs
  2554. wmb_loop    move.w  $dff018,d0  ;WAIT until all data sent
  2555.         btst    #12,d0      ;test TSRE bit of SERDAT
  2556.         beq.s   wmb_loop
  2557.         move.w  #$0001,$dff09a  ;disable TBE
  2558.         movea.l 4.w,a6
  2559.         move.l  prevtbe-DB(a5),a1
  2560.         moveq   #0,d0
  2561.         jsr -$a2(a6)    ;SetIntVector()
  2562. fs_noptbe   movea.l miscresbase-DB(a5),a6
  2563.         moveq   #0,d0       ;serial port
  2564.         jsr -$c(a6)     ;FreeMiscResource()
  2565.         moveq   #1,d0       ;serial bits
  2566.         jsr -$c(a6)
  2567.         clr.b   serportalloc-DB(a5)
  2568.         clr.b   lastcmdbyte-DB(a5)
  2569. retfs:      movem.l (sp)+,a5-a6
  2570.         rts
  2571.  
  2572. ; Message number in d0.
  2573. _InitMIDIDump:  tst.b   serportalloc
  2574.         beq.s   idd_rts
  2575.         movem.l a5/a6,-(sp) ;a1 = data pointer, d1 = length
  2576.         lea DB,a5
  2577.         movea.l 4.w,a6          ;ExecBase
  2578.         jsr -$78(a6)        ;Disable()
  2579.         cmp.w   #16,dqentries-DB(a5)    ;dump queue full?
  2580.         bge.s   idd_exit        ;exit without doing anything
  2581.         lea dqwriteptr-DB(a5),a1
  2582.         movea.l (a1),a0
  2583.         move.w  d0,(a0)+        ;store message number
  2584.         cmpa.l  a1,a0           ;queue end?
  2585.         bne.s   idd_noresetbuff
  2586.         lea dumpqueue-DB(a5),a0 ;reset write pointer
  2587. idd_noresetbuff move.l  a0,(a1)         ;and write it back.
  2588.         addq.w  #1,dqentries-DB(a5)
  2589.         tst.b   sysx-DB(a5)     ;already sending data?
  2590.         bne.s   idd_exit        ;yes. Don't initiate new send.
  2591.         clr.b   lastcmdbyte-DB(a5)
  2592.         bsr StartNewDump
  2593.         move.w  $dff018,d0      ;SERDATR
  2594.         btst    #13,d0
  2595.         beq.s   idd_exit
  2596.         move.w  #$8001,$dff09c      ;request TBE
  2597. idd_exit    jsr -$7e(a6)        ;Enable()
  2598.         movem.l (sp)+,a5/a6
  2599. idd_rts     rts
  2600.  
  2601. SerIntHandler:  move.w  #$4000,$9a(a0)  ;disable..(Interrupts are enabled anyway)
  2602.         move.w  #1,$9c(a0)          ;clear intreq bit
  2603.         tst.b   sysx-buffptr(a1)        ;sysx??
  2604.         bne.s   sih_sysx
  2605.         move.w  bytesinbuff-buffptr(a1),d0  ;bytesinbuff
  2606.         beq.s   exsih               ;buffer empty
  2607.         movea.l readbuffptr-buffptr(a1),a5  ;get buffer read pointer
  2608.         move.w  #$100,d1            ;Stop bit
  2609.         move.b  (a5)+,d1            ;get byte
  2610.         move.w  d1,$30(a0)          ;and push it to SERDAT
  2611.         cmpa.l  a1,a5               ;shall we reset ptr?
  2612.         bne.s   norrbuffptr         ;not yet..
  2613.         lea -256(a1),a5
  2614. norrbuffptr subq.w  #1,d0               ;one less bytes in buffer
  2615.         move.w  d0,bytesinbuff-buffptr(a1)  ;remember it
  2616.         move.l  a5,readbuffptr-buffptr(a1)  ;push new read ptr back
  2617. exsih       move.w  #$c000,$9a(a0)
  2618.         rts
  2619. sih_sysx    move.w  #$100,d1
  2620.         movea.l sysxptr-buffptr(a1),a5  ;data pointer
  2621.         move.b  (a5)+,d1
  2622.         move.l  a5,sysxptr-buffptr(a1)
  2623.         move.w  d1,$30(a0)      ;-> SERDAT
  2624.         subq.l  #1,sysxleft-buffptr(a1) ;sub data left length
  2625.         bne.s   exsih       ;not 0w
  2626.         lea DB,a5
  2627.         clr.b   lastcmdbyte-DB(a5)
  2628.         bsr.s   StartNewDump
  2629.         bra.s   exsih
  2630.  
  2631. StartNewDump:   tst.w   dqentries-DB(a5)    ;queue empty?
  2632.         beq.s   snd_exit2
  2633.         movea.l dqreadptr-DB(a5),a1 ;get read pointer
  2634.         move.w  (a1)+,d0        ;get message number (D0)
  2635.         cmpa.l  #dqwriteptr,a1      ;queue end?
  2636.         bne.s   snd_noresetbuff
  2637.         lea dumpqueue-DB(a5),a1 ;reset write pointer
  2638. snd_noresetbuff move.l  a1,dqreadptr-DB(a5) ;and write it back.
  2639.         subq.w  #1,dqentries-DB(a5)
  2640. ; then attempt to search the given message (# in D0)
  2641.         move.l  _module-DB(a5),d1
  2642.         beq.s   StartNewDump
  2643.         move.l  d1,a1
  2644.         move.l  mmd_expdata(a1),d1
  2645.         beq.s   StartNewDump
  2646.         move.l  d1,a1
  2647.         move.l  52(a1),d1       ;exp_dump
  2648.         beq.s   StartNewDump
  2649.         move.l  d1,a1
  2650.         cmp.w   (a1),d0
  2651.         bge.s   StartNewDump
  2652.         addq.l  #8,a1           ;points to MMDDump ptr table
  2653.         add.w   d0,d0
  2654.         add.w   d0,d0           ;number *= 4
  2655.         adda.w  d0,a1
  2656.         movea.l (a1),a1
  2657. ; initialize send variables (msg addr. in A0)
  2658. snd_found   move.l  (a1)+,sysxleft-DB(a5)   ;length
  2659.         move.l  (a1),sysxptr-DB(a5) ;data pointer
  2660.         st  sysx-DB(a5)
  2661.         rts
  2662. snd_exit2   clr.b   sysx-DB(a5)     ;finish dump
  2663.         rts
  2664.  
  2665. _AddMIDIData    move.l  a6,-(sp)
  2666.         lea DB,a6
  2667.         bsr.s   _AddMIDId
  2668.         move.l  (sp)+,a6
  2669.         rts
  2670.  
  2671. _AddMIDId   movem.l a2-a3/a5,-(sp)
  2672.         tst.b   serportalloc-DB(a6)
  2673.         beq.s   retamd1
  2674.         movea.l 4.w,a5
  2675.         lea $dff09a,a3
  2676.         move.w  #$4000,(a3) ;Disable interrupts
  2677.         addq.b  #1,$126(a5) ;ExecBase->IDNestCnt
  2678.         lea buffptr-DB(a6),a2   ;end of buffer (ptr)
  2679.         move.w  -130(a3),d1 ;-130(a3) = $dff018 (SERDATR)
  2680.         btst    #13,d1
  2681.         beq.s   noTBEreq
  2682.         move.w  #$8001,2(a3)    ;request TBE [2(a3) = $dff09c]
  2683. noTBEreq    movea.l (a2),a1     ;buffer pointer
  2684.         subq.w  #1,d0       ;-1 for DBF
  2685. adddataloop move.b  (a0)+,d1    ;get byte
  2686.         bpl.s   norscheck   ;this isn't a status byte
  2687.         cmp.b   #$ef,d1     ;ignore system messages
  2688.         bhi.s   norscheck
  2689.         cmp.b   lastcmdbyte-DB(a6),d1   ;same as previous status byte?
  2690.         beq.s   samesb          ;yes, skip
  2691.         move.b  d1,lastcmdbyte-DB(a6)   ;no, don't skip but store.
  2692. norscheck   move.b  d1,(a1)+        ;push to midi send buffer
  2693.         addq.w  #1,8(a2)
  2694. samesb      cmpa.l  a2,a1           ;end of buffer??
  2695.         bne.s   noresbuffptr        ;no.
  2696.         lea sendbuffer-DB(a6),a1    ;reset
  2697. noresbuffptr    dbf d0,adddataloop
  2698.         move.l  a1,(a2)         ;push back new buffer ptr
  2699.         subq.b  #1,$126(a5)
  2700.         bge.s   retamd1
  2701.         move.w  #$c000,(a3) ;enable interrupts again
  2702. retamd1     movem.l (sp)+,a2-a3/a5
  2703.         rts
  2704.     ENDC
  2705.  
  2706.         DATA
  2707. DB:     ;Data base pointer
  2708.     IFNE    MIDI
  2709. sendbuffer  ds.b    256
  2710. buffptr     dc.l    sendbuffer
  2711. readbuffptr dc.l    sendbuffer
  2712. bytesinbuff dc.w    0
  2713. sysx        dc.b    0
  2714. lastcmdbyte dc.b    0
  2715. sysxptr     dc.l    0
  2716. sysxleft    dc.l    0
  2717. dumpqueue   ds.w    16
  2718. dqwriteptr  dc.l    dumpqueue
  2719. dqreadptr   dc.l    dumpqueue
  2720. dqentries   dc.w    0
  2721.     ENDC
  2722. miscresbase dc.l    0
  2723. timerdiv    dc.l    470000
  2724.     IFNE    AUDDEV
  2725. audiodevopen    dc.b    0
  2726. sigbitnum   dc.b    -1
  2727.     ENDC
  2728.     IFNE    MIDI
  2729. serportalloc    dc.b    0
  2730.     ENDC
  2731.         even
  2732.     IFNE    MIDI
  2733. preschgdata dc.l    0
  2734. noteondata  dc.l    0
  2735.     ENDC
  2736. _module     dc.l    0
  2737. dmaonmsk    dc.w    0 ;\_May not be
  2738.     IFNE    MIDI
  2739. bytesinnotebuff dc.w    0 ;/ separated!
  2740. noteonbuff  ds.b    (MAX_NUMTRACKS+2)*3
  2741.         even
  2742. intrson     dc.b    0,0
  2743. prevtbe     dc.l    0
  2744.     ENDC
  2745.     IFNE    CIAB
  2746. _ciaresource    dc.l    0
  2747. craddr      dc.l    0
  2748.         dc.l    0   ;tloaddr
  2749.         dc.l    0   ;thiaddr
  2750.     ENDC
  2751. timerinterrupt  dc.w    0,0,0,0,0
  2752.         dc.l    timerintname,DB
  2753.         dc.l    _IntHandler
  2754.     IFNE    MIDI
  2755. serinterrupt    dc.w    0,0,0,0,0
  2756.         dc.l    serintname,buffptr,SerIntHandler
  2757.     ENDC
  2758.     IFNE    AUDDEV
  2759. allocport   dc.l    0,0 ;succ, pred
  2760.         dc.b    4,0 ;NT_MSGPORT
  2761.         dc.l    0   ;name
  2762.         dc.b    0,0 ;flags = PA_SIGNAL
  2763.         dc.l    0   ;task
  2764. reqlist     dc.l    0,0,0   ;list head, tail and tailpred
  2765.         dc.b    5,0
  2766. allocreq    dc.l    0,0
  2767.         dc.b    0,127   ;NT_UNKNOWN, use maximum priority (127)
  2768.         dc.l    0,allocport ;name, replyport
  2769.         dc.w    68      ;length
  2770.         dc.l    0   ;io_Device
  2771.         dc.l    0   ;io_Unit
  2772.         dc.w    0   ;io_Command
  2773.         dc.b    0,0 ;io_Flags, io_Error
  2774.         dc.w    0   ;ioa_AllocKey
  2775.         dc.l    sttempo ;ioa_Data
  2776.         dc.l    1   ;ioa_Length
  2777.         dc.w    0,0,0   ;ioa_Period, Volume, Cycles
  2778.         dc.w    0,0,0,0,0,0,0,0,0,0 ;ioa_WriteMsg
  2779. audiodevname    dc.b    'audio.device',0
  2780.     ENDC
  2781.     IFNE    CIAB
  2782. cianame     dc.b    'ciax.resource',0
  2783. _timeropen  dc.b    0
  2784.     ENDC
  2785. timerintname    dc.b    'OMEDTimerInterrupt',0
  2786.     IFNE    MIDI
  2787. serintname  dc.b    'OMEDSerialInterrupt',0
  2788. miscresname dc.b    'misc.resource',0
  2789. serdev      dc.b    'serial.device',0
  2790. medname     dc.b    'OctaMED Pro modplayer',0
  2791.     ENDC
  2792.         even
  2793.     IFNE    MIDI
  2794. midiresd    dc.b    $e0,$00,$40,$b0,$01,$00
  2795.  
  2796. midicontrnum    ds.b    16
  2797.  
  2798. prevmidicpres   dc.l    0,0,0,0,0,0,0,0 ; 16 * 2 bytes
  2799.  
  2800. prevmidipbend   dc.w    $2000,$2000,$2000,$2000,$2000,$2000,$2000,$2000
  2801.         dc.w    $2000,$2000,$2000,$2000,$2000,$2000,$2000,$2000
  2802.     ENDC
  2803. ; TRACK-data structures (see definitions at the end of this file)
  2804. t03d        ds.b    22
  2805.         dc.l    $dff0a0
  2806.         ds.b    71
  2807.         dc.b    $ff
  2808.         ds.b    22
  2809.         dc.l    $dff0b0
  2810.         ds.b    71
  2811.         dc.b    $ff
  2812.         ds.b    22
  2813.         dc.l    $dff0c0
  2814.         ds.b    71
  2815.         dc.b    $ff
  2816.         ds.b    22
  2817.         dc.l    $dff0d0
  2818.         ds.b    71
  2819.         dc.b    $ff
  2820. t463d       ds.b    (MAX_NUMTRACKS-4)*T415SZ
  2821. trackdataptrs   dc.l    t03d,t03d+T03SZ,t03d+2*T03SZ,t03d+3*T03SZ
  2822. ; Build pointer table. This works on Devpac assembler, other assemblers
  2823. ; may need modifications.
  2824. TRKCOUNT    SET 0
  2825.         REPT    (MAX_NUMTRACKS-4)
  2826.         dc.l    t463d+TRKCOUNT
  2827. TRKCOUNT    SET TRKCOUNT+T415SZ
  2828.         ENDR
  2829.  
  2830. nextblock   dc.b    0 ;\ DON'T SEPARATE
  2831. nxtnoclrln  dc.b    0 :/
  2832. numtracks   dc.w    0 ;\ DON'T SEPARATE
  2833. numlines    dc.w    0 ;/
  2834. nextblockline   dc.w    0
  2835. rptline     dc.w    0 ;\ DON'T SEPARATE
  2836. rptcounter  dc.w    0 ;/
  2837. blkdelay    dc.w    0   ;block delay (PT PatternDelay)
  2838. bpmcounter  dc.w    0
  2839. bpmdiv      dc.l    3546895/2
  2840.  
  2841. ; Fields in struct InstrExt (easier to access this way rather than
  2842. ; searching through the module).
  2843. holdvals    ds.b 63
  2844. decays      ds.b 63
  2845. finetunes   ds.b 63
  2846. flags       ds.b 63
  2847. ext_midipsets   ds.w 63
  2848.  
  2849. ; Below are the period tables. There's one table for each finetune position.
  2850.     IFNE    SYNTH|IFFMOCT
  2851.     dc.w    3424,3232,3048,2880,2712,2560,2416,2280,2152,2032,1920,1812
  2852.     dc.w    1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,906
  2853.     ENDC
  2854. per0    dc.w    856,808,762,720,678,640,604,570,538,508,480,453
  2855.     dc.w    428,404,381,360,339,320,302,285,269,254,240,226
  2856.     dc.w    214,202,190,180,170,160,151,143,135,127,120,113
  2857.     dc.w    214,202,190,180,170,160,151,143,135,127,120,113
  2858.     dc.w    214,202,190,180,170,160,151,143,135,127,120,113
  2859.     dc.w    214,202,190,180,170,160,151,143,135,127,120,113
  2860.     IFNE    SYNTH|IFFMOCT
  2861.     dc.w    3400,3209,3029,2859,2699,2547,2404,2269,2142,2022,1908,1801
  2862.     dc.w    1700,1605,1515,1430,1349,1274,1202,1135,1071,1011,954,901
  2863.     ENDC
  2864. per1    dc.w    850,802,757,715,674,637,601,567,535,505,477,450
  2865.     dc.w    425,401,379,357,337,318,300,284,268,253,239,225
  2866.     dc.w    213,201,189,179,169,159,150,142,134,126,119,113
  2867.     dc.w    213,201,189,179,169,159,150,142,134,126,119,113
  2868.     dc.w    213,201,189,179,169,159,150,142,134,126,119,113
  2869.     dc.w    213,201,189,179,169,159,150,142,134,126,119,113
  2870.     IFNE    SYNTH|IFFMOCT
  2871.     dc.w    3376,3187,3008,2839,2680,2529,2387,2253,2127,2007,1895,1788
  2872.     dc.w    1688,1593,1504,1419,1340,1265,1194,1127,1063,1004,947,894
  2873.     ENDC
  2874. per2    dc.w    844,796,752,709,670,632,597,563,532,502,474,447
  2875.     dc.w    422,398,376,355,335,316,298,282,266,251,237,224
  2876.     dc.w    211,199,188,177,167,158,149,141,133,125,118,112
  2877.     dc.w    211,199,188,177,167,158,149,141,133,125,118,112
  2878.     dc.w    211,199,188,177,167,158,149,141,133,125,118,112
  2879.     dc.w    211,199,188,177,167,158,149,141,133,125,118,112
  2880.     IFNE    SYNTH|IFFMOCT
  2881.     dc.w    3352,3164,2986,2819,2660,2511,2370,2237,2112,1993,1881,1776
  2882.     dc.w    1676,1582,1493,1409,1330,1256,1185,1119,1056,997,941,888
  2883.     ENDC
  2884. per3    dc.w    838,791,746,704,665,628,592,559,528,498,470,444
  2885.     dc.w    419,395,373,352,332,314,296,280,264,249,235,222
  2886.     dc.w    209,198,187,176,166,157,148,140,132,125,118,111
  2887.     dc.w    209,198,187,176,166,157,148,140,132,125,118,111
  2888.     dc.w    209,198,187,176,166,157,148,140,132,125,118,111
  2889.     dc.w    209,198,187,176,166,157,148,140,132,125,118,111
  2890.     IFNE    SYNTH|IFFMOCT
  2891.     dc.w    3328,3141,2965,2799,2641,2493,2353,2221,2097,1979,1868,1763
  2892.     dc.w    1664,1571,1482,1399,1321,1247,1177,1111,1048,989,934,881
  2893.     ENDC
  2894. per4    dc.w    832,785,741,699,660,623,588,555,524,495,467,441
  2895.     dc.w    416,392,370,350,330,312,294,278,262,247,233,220
  2896.     dc.w    208,196,185,175,165,156,147,139,131,124,117,110
  2897.     dc.w    208,196,185,175,165,156,147,139,131,124,117,110
  2898.     dc.w    208,196,185,175,165,156,147,139,131,124,117,110
  2899.     dc.w    208,196,185,175,165,156,147,139,131,124,117,110
  2900.     IFNE    SYNTH|IFFMOCT
  2901.     dc.w    3304,3119,2944,2778,2622,2475,2336,2205,2081,1965,1854,1750
  2902.     dc.w    1652,1559,1472,1389,1311,1238,1168,1103,1041,982,927,875
  2903.     ENDC
  2904. per5    dc.w    826,779,736,694,655,619,584,551,520,491,463,437
  2905.     dc.w    413,390,368,347,328,309,292,276,260,245,232,219
  2906.     dc.w    206,195,184,174,164,155,146,138,130,123,116,109
  2907.     dc.w    206,195,184,174,164,155,146,138,130,123,116,109
  2908.     dc.w    206,195,184,174,164,155,146,138,130,123,116,109
  2909.     dc.w    206,195,184,174,164,155,146,138,130,123,116,109
  2910.     IFNE    SYNTH|IFFMOCT
  2911.     dc.w    3280,3096,2922,2758,2603,2457,2319,2189,2066,1950,1841,1738
  2912.     dc.w    1640,1548,1461,1379,1302,1229,1160,1095,1033,975,920,869
  2913.     ENDC
  2914. per6    dc.w    820,774,730,689,651,614,580,547,516,487,460,434
  2915.     dc.w    410,387,365,345,325,307,290,274,258,244,230,217
  2916.     dc.w    205,193,183,172,163,154,145,137,129,122,115,109
  2917.     dc.w    205,193,183,172,163,154,145,137,129,122,115,109
  2918.     dc.w    205,193,183,172,163,154,145,137,129,122,115,109
  2919.     dc.w    205,193,183,172,163,154,145,137,129,122,115,109
  2920.     IFNE    SYNTH|IFFMOCT
  2921.     dc.w    3256,3073,2901,2738,2584,2439,2302,2173,2051,1936,1827,1725
  2922.     dc.w    1628,1537,1450,1369,1292,1220,1151,1087,1026,968,914,862
  2923.     ENDC
  2924. per7    dc.w    814,768,725,684,646,610,575,543,513,484,457,431
  2925.     dc.w    407,384,363,342,323,305,288,272,256,242,228,216
  2926.     dc.w    204,192,181,171,161,152,144,136,128,121,114,108
  2927.     dc.w    204,192,181,171,161,152,144,136,128,121,114,108
  2928.     dc.w    204,192,181,171,161,152,144,136,128,121,114,108
  2929.     dc.w    204,192,181,171,161,152,144,136,128,121,114,108
  2930.     IFNE    SYNTH|IFFMOCT
  2931.     dc.w    3628,3424,3232,3051,2880,2718,2565,2421,2285,2157,2036,1922
  2932.     dc.w    1814,1712,1616,1525,1440,1359,1283,1211,1143,1079,1018,961
  2933.     ENDC
  2934. per_8   dc.w    907,856,808,762,720,678,640,604,570,538,508,480
  2935.     dc.w    453,428,404,381,360,339,320,302,285,269,254,240
  2936.     dc.w    226,214,202,190,180,170,160,151,143,135,127,120
  2937.     dc.w    226,214,202,190,180,170,160,151,143,135,127,120
  2938.     dc.w    226,214,202,190,180,170,160,151,143,135,127,120
  2939.     dc.w    226,214,202,190,180,170,160,151,143,135,127,120
  2940.     IFNE    SYNTH|IFFMOCT
  2941.     dc.w    3588,3387,3197,3017,2848,2688,2537,2395,2260,2133,2014,1901
  2942.     dc.w    1794,1693,1598,1509,1424,1344,1269,1197,1130,1067,1007,950
  2943.     ENDC
  2944. per_7   dc.w    900,850,802,757,715,675,636,601,567,535,505,477
  2945.     dc.w    450,425,401,379,357,337,318,300,284,268,253,238
  2946.     dc.w    225,212,200,189,179,169,159,150,142,134,126,119
  2947.     dc.w    225,212,200,189,179,169,159,150,142,134,126,119
  2948.     dc.w    225,212,200,189,179,169,159,150,142,134,126,119
  2949.     dc.w    225,212,200,189,179,169,159,150,142,134,126,119
  2950.     IFNE    SYNTH|IFFMOCT
  2951.     dc.w    3576,3375,3186,3007,2838,2679,2529,2387,2253,2126,2007,1894
  2952.     dc.w    1788,1688,1593,1504,1419,1339,1264,1193,1126,1063,1003,947
  2953.     ENDC
  2954. per_6   dc.w    894,844,796,752,709,670,632,597,563,532,502,474
  2955.     dc.w    447,422,398,376,355,335,316,298,282,266,251,237
  2956.     dc.w    223,211,199,188,177,167,158,149,141,133,125,118
  2957.     dc.w    223,211,199,188,177,167,158,149,141,133,125,118
  2958.     dc.w    223,211,199,188,177,167,158,149,141,133,125,118
  2959.     dc.w    223,211,199,188,177,167,158,149,141,133,125,118
  2960.     IFNE    SYNTH|IFFMOCT
  2961.     dc.w    3548,3349,3161,2984,2816,2658,2509,2368,2235,2110,1991,1879
  2962.     dc.w    1774,1674,1580,1492,1408,1329,1254,1184,1118,1055,996,940
  2963.     ENDC
  2964. per_5   dc.w    887,838,791,746,704,665,628,592,559,528,498,470
  2965.     dc.w    444,419,395,373,352,332,314,296,280,264,249,235
  2966.     dc.w    222,209,198,187,176,166,157,148,140,132,125,118
  2967.     dc.w    222,209,198,187,176,166,157,148,140,132,125,118
  2968.     dc.w    222,209,198,187,176,166,157,148,140,132,125,118
  2969.     dc.w    222,209,198,187,176,166,157,148,140,132,125,118
  2970.     IFNE    SYNTH|IFFMOCT
  2971.     dc.w    3524,3326,3140,2963,2797,2640,2492,2352,2220,2095,1978,1867
  2972.     dc.w    1762,1663,1570,1482,1399,1320,1246,1176,1110,1048,989,933
  2973.     ENDC
  2974. per_4   dc.w    881,832,785,741,699,660,623,588,555,524,494,467
  2975.     dc.w    441,416,392,370,350,330,312,294,278,262,247,233
  2976.     dc.w    220,208,196,185,175,165,156,147,139,131,123,117
  2977.     dc.w    220,208,196,185,175,165,156,147,139,131,123,117
  2978.     dc.w    220,208,196,185,175,165,156,147,139,131,123,117
  2979.     dc.w    220,208,196,185,175,165,156,147,139,131,123,117
  2980.     IFNE    SYNTH|IFFMOCT
  2981.     dc.w    3500,3304,3118,2943,2778,2622,2475,2336,2205,2081,1964,1854
  2982.     dc.w    1750,1652,1559,1472,1389,1311,1237,1168,1102,1041,982,927
  2983.     ENDC
  2984. per_3   dc.w    875,826,779,736,694,655,619,584,551,520,491,463
  2985.     dc.w    437,413,390,368,347,328,309,292,276,260,245,232
  2986.     dc.w    219,206,195,184,174,164,155,146,138,130,123,116
  2987.     dc.w    219,206,195,184,174,164,155,146,138,130,123,116
  2988.     dc.w    219,206,195,184,174,164,155,146,138,130,123,116
  2989.     dc.w    219,206,195,184,174,164,155,146,138,130,123,116
  2990.     IFNE    SYNTH|IFFMOCT
  2991.     dc.w    3472,3277,3093,2920,2756,2601,2455,2317,2187,2064,1949,1839
  2992.     dc.w    1736,1639,1547,1460,1378,1301,1228,1159,1094,1032,974,920
  2993.     ENDC
  2994. per_2   dc.w    868,820,774,730,689,651,614,580,547,516,487,460
  2995.     dc.w    434,410,387,365,345,325,307,290,274,258,244,230
  2996.     dc.w    217,205,193,183,172,163,154,145,137,129,122,115
  2997.     dc.w    217,205,193,183,172,163,154,145,137,129,122,115
  2998.     dc.w    217,205,193,183,172,163,154,145,137,129,122,115
  2999.     dc.w    217,205,193,183,172,163,154,145,137,129,122,115
  3000.     IFNE    SYNTH|IFFMOCT
  3001.     dc.w    3448,3254,3072,2899,2737,2583,2438,2301,2172,2050,1935,1827
  3002.     dc.w    1724,1627,1536,1450,1368,1292,1219,1151,1086,1025,968,913
  3003.     ENDC
  3004. per_1   dc.w    862,814,768,725,684,646,610,575,543,513,484,457
  3005.     dc.w    431,407,384,363,342,323,305,288,272,256,242,228
  3006.     dc.w    216,203,192,181,171,161,152,144,136,128,121,114
  3007.     dc.w    216,203,192,181,171,161,152,144,136,128,121,114
  3008.     dc.w    216,203,192,181,171,161,152,144,136,128,121,114
  3009.     dc.w    216,203,192,181,171,161,152,144,136,128,121,114
  3010.  
  3011. _periodtable
  3012.     dc.l    per_8,per_7,per_6,per_5,per_4,per_3,per_2,per_1,per0
  3013.     dc.l    per1,per2,per3,per4,per5,per6,per7
  3014.  
  3015.     IFND    __G2
  3016.         section "datachip",data,chip ;for A68k
  3017.     ENDC
  3018.     IFD __G2
  3019.         section "datachip",data_c ;this is for Devpac 2
  3020.     ENDC
  3021.         XDEF    _modnum
  3022.     IFNE    EASY
  3023. easymod     INCBIN  "module"    ;<<<<< MODULE NAME HERE!
  3024.     ENDC
  3025. _chipzero   dc.l    0
  3026. _modnum     dc.w    0   ;number of module to play
  3027.  
  3028. ; the track-data structure definition:
  3029. trk_prevnote    EQU 0   ;previous note number
  3030. trk_previnstr   EQU 1   ;previous instrument number
  3031. trk_prevvol EQU 2   ;previous volume
  3032. trk_prevmidich  EQU 3   ;previous MIDI channel
  3033. trk_cmd     EQU 4   ;command (the 3rd number from right)
  3034. trk_cmdqual EQU 5   ;command qualifier (infobyte, databyte..)
  3035. trk_prevmidin   EQU 6   ;previous MIDI note
  3036. trk_noteoffcnt  EQU 7   ;note-off counter (hold)
  3037. trk_inithold    EQU 8   ;default hold for this instrument
  3038. trk_initdecay   EQU 9   ;default decay for....
  3039. trk_stransp EQU 10  ;instrument transpose
  3040. trk_finetune    EQU 11  ;finetune
  3041. trk_soffset EQU 12  ;new sample offset
  3042. trk_previnstra  EQU 14  ;address of the previous instrument data
  3043. trk_trackvol    EQU 18
  3044. ;   the following data only on tracks 0 - 3
  3045. trk_prevper EQU 20  ;previous period
  3046. trk_audioaddr   EQU 22  ;hardware audio channel base address
  3047. trk_sampleptr   EQU 26  ;pointer to sample
  3048. trk_samplelen   EQU 30  ;length (>> 1)
  3049. trk_porttrgper  EQU 32  ;portamento (cmd 3) target period
  3050. trk_vibshift    EQU 34  ;vibrato shift for ASR instruction
  3051. trk_vibrspd EQU 35  ;vibrato speed/size (cmd 4 qualifier)
  3052. trk_vibrsz  EQU 36  ;vibrato size
  3053. trk_synthptr    EQU 38  ;pointer to synthetic/hybrid instrument
  3054. trk_arpgoffs    EQU 42  ;SYNTH: current arpeggio offset
  3055. trk_arpsoffs    EQU 44  ;SYNTH: arpeggio restart offset
  3056. trk_volxcnt EQU 46  ;SYNTH: volume execute counter
  3057. trk_wfxcnt  EQU 47  ;SYNTH: waveform execute counter
  3058. trk_volcmd  EQU 48  ;SYNTH: volume command pointer
  3059. trk_wfcmd   EQU 50  ;SYNTH: waveform command pointer
  3060. trk_volwait EQU 52  ;SYNTH: counter for WAI (volume list)
  3061. trk_wfwait  EQU 53  ;SYNTH: counter for WAI (waveform list)
  3062. trk_synthvibspd EQU 54  ;SYNTH: vibrato speed
  3063. trk_wfchgspd    EQU 56  ;SYNTH: period change
  3064. trk_perchg  EQU 58  ;SYNTH: curr. period change from trk_prevper
  3065. trk_envptr  EQU 60  ;SYNTH: envelope waveform pointer
  3066. trk_synvibdep   EQU 64  ;SYNTH: vibrato depth
  3067. trk_synvibwf    EQU 66       ;SYNTH: vibrato waveform
  3068. trk_synviboffs  EQU 70  ;SYNTH: vibrato pointer
  3069. trk_initvolxspd EQU 72  ;SYNTH: volume execute speed
  3070. trk_initwfxspd  EQU 73  ;SYNTH: waveform execute speed
  3071. trk_volchgspd   EQU 74  ;SYNTH: volume change
  3072. trk_prevnote2   EQU 75  ;SYNTH: previous note
  3073. trk_synvol  EQU 76  ;SYNTH: current volume
  3074. trk_synthtype   EQU 77  ;>0 = synth, -1 = hybrid, 0 = no synth
  3075. trk_periodtbl   EQU 78  ;pointer to period table
  3076. trk_prevportspd EQU 82  ;portamento (cmd 3) speed
  3077. trk_decay   EQU 84  ;decay
  3078. trk_fadespd EQU 85  ;decay speed
  3079. trk_envrestart  EQU 86  ;SYNTH: envelope waveform restart point
  3080. trk_envcount    EQU 90  ;SYNTH: envelope counter
  3081. trk_split   EQU 91  ;0 = this channel not splitted (OctaMED V2)
  3082. trk_vibroffs    EQU 92  ;vibrato table offset \ DON'T SEPARATE
  3083. trk_tremoffs    EQU 93  ;tremolo table offset /
  3084. trk_tremsz  EQU 94  ;tremolo size
  3085. trk_tremspd EQU 96  ;tremolo speed
  3086. trk_tempvol EQU 97  ;temporary volume (for tremolo)
  3087.         END